Jon Miles
Jon Miles

Reputation: 9863

mongoose save fails without error

As the title suggests I'm having problems with mongoose save method, which fails but does not produce an error.

I actually know why it fails, which is down to the userId field being marked as required but not being provided... but I don't know why it doesn't throw an error. I've exhausted google and stackoverflow looking at similar suggestions with no luck, so throwing it open to anyone who can help me!

Here's the code...

Model.js

var mongoose = require('mongoose');

var TimeSchema = new mongoose.Schema({
    client: String,
    matter: String,
    activity: String,
    tags: String,
    description: String,
    comments: [String],
    startTime: Date,
    startTimeUTC: Number,
    endTime: Date,
    endTimeUTC: Number,
    duration: Number, 
    durationRnd: Number,    
    durationUnits: Number,  
    billable: Boolean,
    rate: Number,
    total: Number,
    user: String,
    userId: { type: mongoose.Schema.ObjectId, required: true }
}, {safe: true});

mongoose.model("Time", TimeSchema);


Controller.js

exports.addTime = function (req, res) {

    console.log('Adding time: ' + JSON.stringify(req.body));
    var time = new Time(req.body);
    time.save(function (err) {
        if (err) { res.send({'error' : err}); }
        res.send(time);
    });
}

EDIT - To clarify the callback is being called, take the following code for example.

exports.addTime = function (req, res) {

    console.log('Adding time: ' + JSON.stringify(req.body));
    var time = new Time(req.body);
    console.log("time = " + time);
    // TODO user
    time.save(function (err) {
        if (err) { handleError(res, err); }
        console.log("ok");
        Time.findById(time._id, function (err, found) {
            console.log("found = " + found);
        });
        res.send(time);

});

}

and here's the console output

Adding time: {"description":"test","client":"","matter":"","activity":"","rate":
"","startTime":"2013-11-30T19:58:43.000Z","startTimeUTC":"1385841523000","endTim
e":"2013-11-30T19:58:45.000Z","endTimeUTC":"1385841525000","startLocale":"19:58"
,"startTimeLocale":"19:58:43","endLocale":"19:58","endTimeLocale":"19:58:45"}
time = { description: 'test',
  client: '',
  matter: '',
  activity: '',
  rate: null,
  startTime: Sat Nov 30 2013 19:58:43 GMT+0000 (GMT Standard Time),
  startTimeUTC: 1385841523000,
  endTime: Sat Nov 30 2013 19:58:45 GMT+0000 (GMT Standard Time),
  endTimeUTC: 1385841525000,
  startTimeLocale: '19:58:43',
  endTimeLocale: '19:58:45',
  _id: 529a43750a366b6419000001,
  comments: [] }
ok
POST /api/times 200 14ms - 313b
found = null

Upvotes: 16

Views: 19182

Answers (7)

Mandrake... Mandrake.
Mandrake... Mandrake.

Reputation: 21

Not directly related to the scenario described in the post, but I was getting the same error.

The issue was that I was not calling next(); at the end of the pre('save') function on the model definition.

For example:

cartSchema.pre('save', function(next) {

  const currentDate = new Date();
  this.modified = currentDate;

  if (this.isNew) {
    this.created = currentDate;
    this.cartid = uuidv4();
  }
  next(); // this was missing :'(
  
});

Upvotes: 0

Angelo Borrelli
Angelo Borrelli

Reputation: 1

For anyone can face a similar issue, I found that when populating a mongoose schema object from a json object that actually owns its “_id” property (even set to “null”), insert fails with no error. Example:

var json = JSON.parse(req.body.time);
var time = new Time(json);

assuming that json._id is defined, no matter it's declared as a new "Time", when you try to insert with:

time.save(function (error) {
    if (error) { res.send({'error' : error}); }
    res.send(time);
});

error variabile is null but item was never inserted. In this case I solved by deleting "_id" property before populating mongoose object so final code as follows:

var json = JSON.parse(req.body.time);
delete json._id;
var time = new Time(json);
time.save(function (error) {
    if (error) { res.send({'error' : error}); }
    res.send(time);
});

Regards

Angelo

Upvotes: 0

xiaopf
xiaopf

Reputation: 1

UserSchema.pre('save',function(next){
  var currentDate=new Date();
  this.updatedAt=currentDate;
  if(!this.createdAt){
    this.createdAt=currentDate;
  };
  next();
});

When I use the .pre('save',fn) to create time, I forgot the next(), causing the data store to fail without error,I hope can help somebody!

Upvotes: 0

MalcolmOcean
MalcolmOcean

Reputation: 2985

I had a situation where the save callback was getting called, but the document wasn't changing. I haven't yet tracked down the root cause (some sort of validation thing probably) but the problem had something to do with one of the changes I made. So I just tried the changes one by one until I found the culprit.

(Feel free to edit this answer if you figure out more of this phenomenon)

Upvotes: -3

shacharsol
shacharsol

Reputation: 2342

My Problem was not solved by using findOne, it was solved by defining the fields i updated , in the model schema. so my code was like that:

          User.findOne({email:data.userData.email}, function (err, user) {
                    if (!err && user!=undefined){
                        console.log(user);
                        var userDiscounts = user.discounts;
                        for(var i=0;i<userDiscounts.length;i++){

                            if (userDiscounts[i]!=undefined && userDiscounts[i].code=="XXXXXX"){
                                userDiscounts[i].claimed = true;

                                console.log('discount claimed');

                            }
                        }
                        user.discounts = userDiscounts;
                        user.fbDiscountClaimed = true;
                        user.save(function(err) {
                            if (err) console.log(err);
                            console.log('Saved Hashve-FB as claimed');


                        });
                    }


                });
            }
        }

But the schema of the discount and user model was missing the definition of types of user.discounts so i added the following:

  var UserSchema = new Schema({
  name: String,
  email: { type: String, lowercase: true },
   role: {
   type: String,
   default: 'user'
 },
  hashedPassword: String,
  provider: String,
  salt: String,
  messages:[],
  discounts:[{
  "name": String,
  "description": String,
  "created_at": String,
  "updated_at": String,
  "code": String,
  "claimed": Boolean
    }
    ],
   facebook: {},
   fbDiscountClaimed:false,
    twitter: {},
  google: {},
  github: {}
  });

Upvotes: 3

M. Ali
M. Ali

Reputation: 2396

It is very possible to run into this error by naively not connecting to the database. Has happened several times to me. Make sure your mongoose.connect() is in place.

Upvotes: 7

Jon Miles
Jon Miles

Reputation: 9863

Problem solved, thanks to robertkelp.

Here's my revised code in case if ever helps anyone, but it appears the error was being thrown I just wasn't handling it correctly.

exports.addTime = function (req, res) {

    console.log('Adding time: ' + JSON.stringify(req.body));
    var time = new Time(req.body);
    time.save(function (err) {
        if (err) { 
            handleError(res, err);
        }
        else {
            res.send(time);
        }
    });
}

Upvotes: 6

Related Questions