Mongoose: findOneAndUpdate with an undefined update doc & timestamps enabled throws a TypeError

Created on 22 Sep 2018  路  1Comment  路  Source: Automattic/mongoose

Hey there. I am submitting a supposed BUG report.

BEHAVIOR
It looks like the fix for #6980 introduced a bug when updating documents with timestamps. This is a stack trace of the issue:

TypeError: Cannot read property '$set' of undefined
at applyTimestampsToUpdate (/usr/src/app/node_modules/mongoose/lib/helpers/update/applyTimestampsToUpdate.js:41)
at model.Query._setTimestampsOnUpdate (schema.js:873)
at callMiddlewareFunction (/usr/src/app/node_modules/kareem/index.js:427)
at next (/usr/src/app/node_modules/kareem/index.js:58)
at Kareem.execPre (/usr/src/app/node_modules/kareem/index.js:86)
at Kareem.wrap (/usr/src/app/node_modules/kareem/index.js:265)
at model.Query._findOneAndUpdate (index.js:339)
at model.Query.Query.findOneAndUpdate (query.js:2658)
at utils.promiseOrCallback (query.js:3652)
at Promise (/usr/src/app/node_modules/mongoose/lib/utils.js:246)
at Promise (<anonymous>)
at Object.promiseOrCallback (/usr/src/app/node_modules/mongoose/lib/utils.js:245)
at model.Query.exec (query.js:3646)
at model.Query.Query.then (query.js:3673)

I had limited time to test, but it appears that it's happening when calling

Model.findOneAndUpdate({
        _id: 'someId' // <-- normal, correct query
    }, 
    undefined,
    {new: true}
});

Notice that the update object is undefined. We've corrected our code for that, but it might catch other people off guard.

EXPECTED BEHAVIOR
Mongoose doesn't throw an error if no update object is passed.

MONGOOSE VERSION(S)
Can reproduce in mongoose 5.2.16 and 5.2.17. Cannot reproduce it in 5.2.15.

confirmed-bug

Most helpful comment

here's a repro script

7041.js

#!/usr/bin/env node
'use strict';

const assert = require('assert');
const mongoose = require('mongoose');
const { Schema, connection} = mongoose;
const GH = 'gh7041';
const URI = `mongodb://localhost:27017/${GH}`;
const OPTS = { family: 4, useNewUrlParser: true };

const schema = new Schema({ name: String })
  .set('timestamps', true);

const Test = mongoose.model('test', schema);

const test = new Test({ name: 'test1' });

async function run() {
  await mongoose.connect(URI, OPTS);
  await connection.dropDatabase();
  await Test.create(test);
  const cond = { _id: test._id };
  const opts = { new: true };
  let doc = await Test.findOneAndUpdate(cond, undefined, opts);
  console.log(doc);
  return connection.close();
}

run().catch(e => {
  console.error(e.stack);
  return connection.close();
});

Output:

issues: ./7041.js
TypeError: Cannot read property '$set' of undefined
    at applyTimestampsToUpdate (/Users/lineus/dev/node/mongoose/node_modules/mongoose/lib/helpers/update/applyTimestampsToUpdate.js:41:26)
    at model.Query._setTimestampsOnUpdate (/Users/lineus/dev/node/mongoose/node_modules/mongoose/lib/schema.js:873:5)
    at callMiddlewareFunction (/Users/lineus/dev/node/mongoose/node_modules/kareem/index.js:427:23)
    at next (/Users/lineus/dev/node/mongoose/node_modules/kareem/index.js:58:7)
    at Kareem.execPre (/Users/lineus/dev/node/mongoose/node_modules/kareem/index.js:86:8)
    at Kareem.wrap (/Users/lineus/dev/node/mongoose/node_modules/kareem/index.js:265:8)
    at model.Query._findOneAndUpdate (/Users/lineus/dev/node/mongoose/node_modules/kareem/index.js:339:11)
    at model.Query.Query.findOneAndUpdate (/Users/lineus/dev/node/mongoose/node_modules/mongoose/lib/query.js:2686:8)
    at utils.promiseOrCallback (/Users/lineus/dev/node/mongoose/node_modules/mongoose/lib/query.js:3680:19)
    at Promise (/Users/lineus/dev/node/mongoose/node_modules/mongoose/lib/utils.js:246:5)
    at new Promise (<anonymous>)
    at Object.promiseOrCallback (/Users/lineus/dev/node/mongoose/node_modules/mongoose/lib/utils.js:245:10)
    at model.Query.exec (/Users/lineus/dev/node/mongoose/node_modules/mongoose/lib/query.js:3674:16)
    at model.Query.Query.then (/Users/lineus/dev/node/mongoose/node_modules/mongoose/lib/query.js:3701:15)
    at process._tickCallback (internal/process/next_tick.js:68:7)
issues:

>All comments

here's a repro script

7041.js

#!/usr/bin/env node
'use strict';

const assert = require('assert');
const mongoose = require('mongoose');
const { Schema, connection} = mongoose;
const GH = 'gh7041';
const URI = `mongodb://localhost:27017/${GH}`;
const OPTS = { family: 4, useNewUrlParser: true };

const schema = new Schema({ name: String })
  .set('timestamps', true);

const Test = mongoose.model('test', schema);

const test = new Test({ name: 'test1' });

async function run() {
  await mongoose.connect(URI, OPTS);
  await connection.dropDatabase();
  await Test.create(test);
  const cond = { _id: test._id };
  const opts = { new: true };
  let doc = await Test.findOneAndUpdate(cond, undefined, opts);
  console.log(doc);
  return connection.close();
}

run().catch(e => {
  console.error(e.stack);
  return connection.close();
});

Output:

issues: ./7041.js
TypeError: Cannot read property '$set' of undefined
    at applyTimestampsToUpdate (/Users/lineus/dev/node/mongoose/node_modules/mongoose/lib/helpers/update/applyTimestampsToUpdate.js:41:26)
    at model.Query._setTimestampsOnUpdate (/Users/lineus/dev/node/mongoose/node_modules/mongoose/lib/schema.js:873:5)
    at callMiddlewareFunction (/Users/lineus/dev/node/mongoose/node_modules/kareem/index.js:427:23)
    at next (/Users/lineus/dev/node/mongoose/node_modules/kareem/index.js:58:7)
    at Kareem.execPre (/Users/lineus/dev/node/mongoose/node_modules/kareem/index.js:86:8)
    at Kareem.wrap (/Users/lineus/dev/node/mongoose/node_modules/kareem/index.js:265:8)
    at model.Query._findOneAndUpdate (/Users/lineus/dev/node/mongoose/node_modules/kareem/index.js:339:11)
    at model.Query.Query.findOneAndUpdate (/Users/lineus/dev/node/mongoose/node_modules/mongoose/lib/query.js:2686:8)
    at utils.promiseOrCallback (/Users/lineus/dev/node/mongoose/node_modules/mongoose/lib/query.js:3680:19)
    at Promise (/Users/lineus/dev/node/mongoose/node_modules/mongoose/lib/utils.js:246:5)
    at new Promise (<anonymous>)
    at Object.promiseOrCallback (/Users/lineus/dev/node/mongoose/node_modules/mongoose/lib/utils.js:245:10)
    at model.Query.exec (/Users/lineus/dev/node/mongoose/node_modules/mongoose/lib/query.js:3674:16)
    at model.Query.Query.then (/Users/lineus/dev/node/mongoose/node_modules/mongoose/lib/query.js:3701:15)
    at process._tickCallback (internal/process/next_tick.js:68:7)
issues:
Was this page helpful?
0 / 5 - 0 ratings

Related issues

gustavomanolo picture gustavomanolo  路  3Comments

lukasz-zak picture lukasz-zak  路  3Comments

adamreisnz picture adamreisnz  路  3Comments

simonxca picture simonxca  路  3Comments

varunjayaraman picture varunjayaraman  路  3Comments