meteor / meteor

Meteor, the JavaScript App Platform

Home Page:https://meteor.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Obscure error: TypeError: Object #<Object> has no method '_defineMutationMethods'

dandv opened this issue · comments

The shortest code to reproduce it doesn't even need a repo. Have a blank packages file and only one client.js file, containing Meteor.Collection("foo");.

The stack trace is:

~/wtf$ meteor reset ; meteor
Project reset.
[[[[[ ~/wtf ]]]]]

Running on: http://localhost:3000/
app/packages/mongo-livedata/collection.js:104
  self._defineMutationMethods();
       ^
TypeError: Object #<Object> has no method '_defineMutationMethods'
    at Object.Meteor.Collection (app/packages/mongo-livedata/collection.js:104:8)
    at app/client.js:1:8
    at /home/dandv/wtf/.meteor/local/build/server/server.js:107:21
    at Array.forEach (native)
    at Function._.each._.forEach (/home/dandv/wtf/.meteor/local/build/server/underscore.js:76:11)
    at run (/home/dandv/wtf/.meteor/local/build/server/server.js:93:7)
Exited with code: 1

Did you mean to write new Meteor.Collection("foo") instead?

It's an annoying feature of JavaScript that it's easy to accidentally call constructors without new. We could choose to make new optional in some of our API's classes (you basically have to put something like if (!(this instanceof Class)) return new Class(args) at the top of every constructor) but for now let's just stick with "you need to know how to use JavaScript constructors". If lots of users run into this issue we can reconsider.

In this case it was trivial to spot the cause of the error, but I reduced the code down from a much larger codebase where I had forgotten to declare a collection. Anyway, now that the error string is googlable, we can wait and see if sufficiently many other users comment on this issue.

I'm only commenting because dandv told me to. I just had this exact issue; forgot new. Glad this was the first hit on Google or it may have taken me awhile :-)

The constructor could check if it's being called with "new" and throw a more understandable error if not:

 Meteor.Collection = function (name, options) {
   var self = this;
+  if (! (self instanceof Meteor.Collection))
+    throw new Error('a Meteor.Collection must be constructed with the "new" operator');

I bumped my head on this one. +1 for the above... I think its pretty unlikely someone would be trying to use it the other way.