Mongoose: Cannot read property '$__original_save' of undefined

Created on 8 Feb 2017  路  16Comments  路  Source: Automattic/mongoose

node 6.9.1
mongodb 2.2.22 (npm version)
mongo 3.3 (actual db)

getting the following error on the latest tag (4.8.1):

Error: Cannot read property '$__original_save' of undefined
      at /var/app/current/node_modules/mongoose/lib/services/model/applyHooks.js:135:16
      at new promise (/var/app/current/node_modules/q/q.js:682:9)
      at wrappedPointCut (/var/app/current/node_modules/mongoose/lib/services/model/applyHooks.js:115:23)
      at _fulfilled (/var/app/current/node_modules/q/q.js:834:54)
      at self.promiseDispatch.done (/var/app/current/node_modules/q/q.js:863:30)
      at Promise.promise.promiseDispatch (/var/app/current/node_modules/q/q.js:796:13)
      at /var/app/current/node_modules/q/q.js:604:44
      at runSingle (/var/app/current/node_modules/q/q.js:137:13)
      at flush (/var/app/current/node_modules/q/q.js:125:13)

Locking my mongoose version to 4.7.5 fixes the issue. Am I missing something important? This happens when creating/saving something new.

needs clarification

Most helpful comment

In this line:

async.parallel([newUser.save, newStudent.save], callback);

the save methods lose reference/context to the models. Instead, you'll want to do:

async.parallel([newUser.save.bind(newUser), newStudent.save.bind(newStudent)], callback);

or

async.parallel([
    (callback) => newUser.save(callback),
    (callback) => newStudent.save(callback)
], callback);

I believe your version used to work at some point (early versions of v4), but that was incorrect/not-well-defined behaviour

All 16 comments

have you set mongoose.Promise = global.Promise before using a promise? And do you have a code snippet / repro script that would help me debug this?

We are having the same issue, but we are using a library called shortId to generate short string ids, for instance

 _id: {
        type: String,
        default: ShortId.generate,
    },
TypeError: Cannot read property '$__original_save' of undefined
      at node_modules/mongoose/lib/services/model/applyHooks.js:135:16
      at wrappedPointCut (node_modules/mongoose/lib/services/model/applyHooks.js:115:23)
      at process._tickDomainCallback (internal/process/next_tick.js:129:7)

We get this error when trying to save on mongoose 4.8.2 (not having this issue on 4.7.6)

I'm gonna need more info than this to debug. Can I see the code that is producing the error message?

Any update on this? Otherwise I'm going to close this from being stale. Unfortunately I need more information to debug this problem :/

Ok got it ;)

Using mongoose 4.8.5 now, before 4.7.6 (working)

consider a simple model like:

const mongoose = require('mongoose');

const thingSchema = new mongoose.Schema({
   name: String,
});

const thingModel = mongoose.model('Thing', thingSchema);

using as such:

const thing1 = new thingModel({ name : 'ogre' });
const thing2 = new thingModel({ name : 'ghost' });

return thing1.save()
     .then(thing2.save);

Results in :

TypeError: Cannot read property '$__original_save' of undefined
      at node_modules/mongoose/lib/services/model/applyHooks.js:137:16
      at wrappedPointCut (node_modules/mongoose/lib/services/model/applyHooks.js:115:23)
      at process._tickDomainCallback (internal/process/next_tick.js:129:7)

where as (works !!!!!):

const thing1 = new thingModel({ name : 'ogre' });
const thing2 = new thingModel({ name : 'ghost' });

return thing1.save()
     .then(() => thing2.save());

I hope this is enough info to fix the issue ;)

same here:

this works:

const updateUser = initUser
      .then(() => {
        user.save();
      });

this results in error: TypeError: Cannot read property \'$__original_save\' of undefined

const updateUser = initUser
      .then(user.save);

version is 4.8.5, was ok with 4.7.* versions

i used async.js then that source 2 objects do parallel time saving

this results in error: TypeError: Cannot read property '$__original_save' of undefined
before that code was working but now why not work help me!!!

module.exports.saveAdmin = function (newUser,newAddress, callback) {
    bcrypt.hash(newUser.password, 10, function (err, hash) {
        if (err) throw err;
        //set hash
        newUser.password = hash;
        console.log('Student is being saved');
        async.parallel([newUser.save,newAddress.save], callback);

    });
};

@valera33 @tommarien be careful of losing function context, you'd get the same error if you did const fn = user.save; fn().then(res => {});. The correct way is either .then(() => user.save()) or .then(user.save.bind(user)), if you pass a member function as a parameter then function context goes away and internally user.save doesn't know what this is.

the same issue as described by @kysemon please someone help.
node v8.0.0
npm 5.0
mongoose 4.10.8

Cannot read property '$__original_save' of undefined

module.exports.saveStudent = function(newUser, newStudent, callback){ bcrypt.hash(newUser.password, 10, (err, hash)=>{ if(err) throw err; newUser.password=hash; console.log("Student is saved"); async.parallel([newUser.save, newStudent.save], callback); }); }

In this line:

async.parallel([newUser.save, newStudent.save], callback);

the save methods lose reference/context to the models. Instead, you'll want to do:

async.parallel([newUser.save.bind(newUser), newStudent.save.bind(newStudent)], callback);

or

async.parallel([
    (callback) => newUser.save(callback),
    (callback) => newStudent.save(callback)
], callback);

I believe your version used to work at some point (early versions of v4), but that was incorrect/not-well-defined behaviour

thanx @dhritzkiv for contributing it is working.....

Thanks for the help @dhritzkiv !

thanks @dhritzkiv it is working now, i was scratching my head over this for 2 days. May i know what was happening and what was causing that error as i don't really understand what caused the error.

@abhanshgiri21 What was happening was the this context was being lost in one of the function call forms. When a function is called by being passed into a callback, for example, this this is whatever is calling that callback. It's easier to demonstrate what's happening with code:

const instance = {
    logThis: function () {
        console.log(this);
    }
};

instance.logThis();
//logs `instance`

setTimeout(() => instance.logThis(), 0);
//logs `instance`

setTimeout(instance.logThis, 0);
//logs `Timeout` since timeout is calling `logThis` and becomes `this` for that call.

//you can force `this` to be what you need it to be with `bind()`:
setTimeout(instance.logThis.bind(instance), 0);
//logs `instance`, since `logThis` has `instance` bound as `this

cool! thanks a lot @dhritzkiv

thq..

Was this page helpful?
0 / 5 - 0 ratings