Mongo/Mongoose Invalid atomic update value error

I am trying to write to write an update to a Mongo document using the Mongoose findOneAndUpdate function. Essentially, I have a document that has an array of another Schema in it, and when I attempt to append more of those schema type, I get the following error:

[Error: Invalid atomic update value for $__. Expected an object, received object]

I'm having a hard time figuring out what this error even means, much less what its source is.

The data I'm attempting to update is as follows:

{ section_id: 51e427ac550dabbb0900000d,
version_id: 7,
last_editor_id: 51ca0c4b5b0669307000000e,
changelog: 'Added modules via merge function.',
committed: true,
_id: 51e45c559b85903d0f00000a,
__v: 0,
modules: 
[ { orderId: 0,
type: 'test',
tags: [],
data: [],
images: [],
content: ["Some Content Here"] },
{ orderId: 1,
type: 'test',
tags: [],
data: [],
images: [],
content: ["Some Content Here"] },
{ orderId: 2,
type: 'test',
tags: [],
data: [],
images: [],
content: ["Some Content Here"] },
{ orderId: 3,
type: 'test',
tags: [],
data: [],
images: [],
content: ["Some Content Here"] },
{ orderId: 4,
type: 'test',
tags: [],
data: [],
images: [],
content: ["Some Content Here"] },
{ orderId: 5,
type: 'test',
tags: [],
data: [],
images: [],
content: ["Some Content Here"] } ] }

The only difference is that when I retrieve it, there are three fewer modules, and I append some new ones to the array.

Would love to hear any thoughts, at least as to what the error means!

This is probably because the updated object is still a Mongoose object. Try to convert it to a JS object before the findOneAndUpdate

object = object.toString()

And delete any potential ID attribute

delete object._id

Or simply

object = object.toObject();

I had the same problem and it turned out I was using $push incorrectly. I was doing

{$push:thing_to_push}

But it needed to be

{$push:{list_to_push_into:thing_to_push}}

@Magrelo and @plus led me to an answer that worked. Something like:

MyModel.findOneAndUpdate({ section_id: '51e427ac550dabbb0900000d' }, mongooseObject.toObject(), { upsert: true }, function(err, results) {
    //...
});

I had the same issue. I ended up by using finOne() method

create a new one if no found, update the existing one if found.

I know there are two operations. but I just haven't find any way to do it in one step.

Another thing to check is if you are sending passing an array of changes to $set. The error message that I received when calling something like this:

db.products.update( { sku: "abc123" },
                { $set: [
                         {quantity: 500},
                         {instock: true}
                        ]
                }
              )

Gave me the [Error: Invalid atomic update value for $set. Expected an object, received object]

Changing it to an object worked.

db.products.update( { sku: "abc123" },
                { $set: {
                          quantity: 500,
                          instock: true
                        }
                }
              )

Try passing update parameter value as string instead of mongoose model object. I was getting same error when I use to pass model object. Below is the code difference.

Code that was having issue:

updateUser: function(req, res) {
**var updatedUserModel = new Users(req.body);**
    Users.findOneAndUpdate({tpx_id:req.params.id}, {$set:**updatedUserModel**}, function(err, User){
           ...
   }
}

Working code:

updateUser: function(req, res) {
   Users.findOneAndUpdate({tpx_id:req.params.id}, {$set:**req.body**}, function(err, User) {
   ...
}