Meteor error - MongoDB: Can't apply $ addToSet modifier on non-array
I am following the recently published book " Getting Started with Meteor.js JavaScript Framework " by Isaac Strack. The book works with Meteor 0.5.0. I am working with version 0.5.4.
In the book, you create a multi-category application into which you insert data to track household items and to whom it can be shared. I deployed the app to meteor subdomain and it works fine. It does not replicate my local MongoDB error.
I'm in chapter 5 and I just removed autopublish from the app and specified my local data feeds.
Locally, just under the Tools category, when I try to add a new item to the category, I get this error in the browser console:
Exception while simulating the effect of invoking '/Lists/update' Error {} Error: Cannot apply $addToSet modifier to non-array
at Error (<anonymous>)
at LocalCollection._modifiers.$addToSet (http://localhost:3000/packages/minimongo/modify.js?e7f02f0df0bff9f0b97236f9548637b7ede1ac74:178:13)
at Function.LocalCollection._modify (http://localhost:3000/packages/minimongo/modify.js?e7f02f0df0bff9f0b97236f9548637b7ede1ac74:53:9)
at LocalCollection._modifyAndNotify (http://localhost:3000/packages/minimongo/minimongo.js?7f5131f0f3d86c8269a6e6db0e2467e28eff6422:474:19)
at LocalCollection.update (http://localhost:3000/packages/minimongo/minimongo.js?7f5131f0f3d86c8269a6e6db0e2467e28eff6422:444:12)
at m.(anonymous function) (http://localhost:3000/packages/mongo-livedata/collection.js?3ef9efcb8726ddf54f58384b2d8f226aaec8fd53:415:36)
at http://localhost:3000/packages/livedata/livedata_connection.js?367884963b120d457819216ff713b2586b266dde:540:25
at _.extend.withValue (http://localhost:3000/packages/meteor/dynamics_browser.js?46b8d1f1158040fcc2beb7906ec2f932871a398d:21:19)
at _.extend.apply (http://localhost:3000/packages/livedata/livedata_connection.js?367884963b120d457819216ff713b2586b266dde:539:47)
at Meteor.Collection.(anonymous function) [as update] (http://localhost:3000/packages/mongo-livedata/collection.js?3ef9efcb8726ddf54f58384b2d8f226aaec8fd53:266:23) logging.js:30
update failed: Internal server error logging.js:30
There is already one item in the tool category that was introduced earlier in the tutorial. If I type into the console lists.findOne({Category:"Tools"});
, I get output that recognizes the item in the object:
Object
Category: "Tools"
_id: "eaa681e1-83f2-49f2-a42b-c6d84e526270"
items: Object
LentTo: "Steve"
Name: "Linear Compression Wrench"
Owner: "me"
__proto__: Object
__proto__: Object
However, the screen output is empty:
Naturally I tried restarting the meteorite server and shutting down the browser, but without permission. I'm new to MongoDB, so it's not clear where to go to understand what is causing this problem, or why.
You can see the application here . You can view the code on GitHub .
source to share
function addItem(list_id, item_name) {
if(!item_name && !list_id)
return;
lists.update({_id:list_id}, {$addToSet:{items:{Name:item_name}}});
}
It looks like you are trying to add an object to the set. You get an error while simulating. Let's try to investigate this error. Code that contains errors:
https://github.com/meteor/meteor/blob/master/packages/minimongo/modify.js
$addToSet: function (target, field, arg) {
var x = target[field];
if (x === undefined)
target[field] = [arg];
else if (!(x instanceof Array))
throw Error("Cannot apply $addToSet modifier to non-array");
else { ...
Oh uh, throw Error("Cannot apply $addToSet modifier to non-array.")
.
Look at your code:
Object
Category: "Tools"
_id: "eaa681e1-83f2-49f2-a42b-c6d84e526270"
...
items: Object
...
items
is an object, not an array! It will fail.
Can you $addToSet
facility with Mongo? Take a look at the code.
https://github.com/mongodb/mongo/blob/4a4f9b1d6dc79d1ba4a7d7eaa9e4eb6d00aa466c/db/update.cpp
case ADDTOSET: {
uassert( 12592 , "$addToSet can only be applied to an array" , in.type() == Array );
...
}
Nope! This is from the old mongo code because the modern codebase is stretching, but the same thing.
I only found one insert
in your code.
'keyup #add-category': function(e, t) {
if (e.which === 13) {
var catVal = String(e.target.value || "");
if (catVal) {
lists.insert({Category:catVal});
Session.set('adding_category', false);
}
}
},
Try it lists.insert({Category:catVal,items:[]})
. So the elements are initialized as an array and not an object when it was first used.
Also, I don't think I'm $addToSet
comparing the objects in the array the way you would like, so consider creating a separate collection items
containing categoryId
.
It's just a coincidence that it works in one place and not another.
source to share
I had the same problem following the same tutorial. When using inserts directly from the manual (Tools and DVDs) minimongo inserts elements as objects instead of arrays. I don't know if it was just a bug or if the code base changed, in any case I changed:
lists.insert({Category:"DVDs", items: {Name:"Mission Impossible", Owner:"me", LentTo:"Alice"}});
to
lists.insert({Category:"DVDs", items: [{Name:"Mission Impossible", Owner:"me",LentTo:"Alice"}]});
just put the elements in [] to force it to the array, and similarly applied tool insertion. Works great.
source to share