Mongoose: ObjectParameterError: Parameter "obj" to Document() must be an object, got false

Created on 13 Nov 2018  路  4Comments  路  Source: Automattic/mongoose

Do you want to request a feature or report a bug?
bug

What is the current behavior?
Upon creating a new model instance (and likely when modifying one), passing false (and some other alternatives) to a field that requires an array of sub-documents (schemas), causes a fatal ObjectParameterError.

If the current behavior is a bug, please provide the steps to reproduce.

The following program can be used to reproduce this:

const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/temp', { useNewUrlParser: true });
const Child = new mongoose.Schema({});
const Parent = new mongoose.Schema({
    children: {
        type: [Child] // only happens for arrays of schemas
    }
});
const ParentModel = mongoose.model('TestParent', Parent);
const model = new ParentModel({
    children: false // also happens for: [false], 0, [0] and [false, 0], but NOT for e.g. [false, 0, true]
});
// error after calling save()
model.save(err => {
    console.log(err.errors.children.message); // should instead give validation error message as such
});

This is the exception that gets thrown:

    throw new ObjectParameterError(obj, 'obj', 'Document');
    ^
ObjectParameterError: Parameter "obj" to Document() must be an object, got false
    at new ObjectParameterError (path\to\project\node_modules\mongoose\lib\error\objectParameter.js:25:11)
    at EmbeddedDocument.Document (path\to\project\node_modules\mongoose\lib\document.js:68:11)
    at EmbeddedDocument [as constructor] (path\to\project\node_modules\mongoose\lib\types\embedded.js:39:12)
    at new EmbeddedDocument (path\to\project\node_modules\mongoose\lib\schema\documentarray.js:75:17)
    at path\to\project\node_modules\mongoose\lib\schema\documentarray.js:187:26
    at DocumentArray.SchemaType.doValidate (path\to\project\node_modules\mongoose\lib\schematype.js:829:12)
    at DocumentArray.doValidate (path\to\project\node_modules\mongoose\lib\schema\documentarray.js:143:35)
    at path\to\project\node_modules\mongoose\lib\document.js:1904:9
    at _combinedTickCallback (internal/process/next_tick.js:131:7)
    at process._tickCallback (internal/process/next_tick.js:180:9)
    at Function.Module.runMain (module.js:695:11)
    at startup (bootstrap_node.js:191:16)
    at bootstrap_node.js:612:3

What is the expected behavior?
Instead of a fatal error being thrown, a validation error should be passed to the save callback. This is already the case for inputs such as true, which simply give a message along the lines of Cast to Array failed for value "true" at path "children".

Please mention your node.js, mongoose and MongoDB version.
Node: 8.11.3, Mongoose: 5.3.12

confirmed-bug

All 4 comments

Thanks for reporting, will fix ASAP

Seems like I got it again when using array push,

 Chat.update( { _id: chatdata._id }, { $push: { message: data.message} }, (err, data) => {
     console.log(err)
     console.log(data)
   })

got :

{ ObjectParameterError: Parameter "obj" to Document() must be an object, got 123213213
    at new ObjectParameterError (C:\learning\chatappexample\server\node_modules\mongoose\lib\error\objectParameter.js:25:11)
    at EmbeddedDocument.Document (C:\learning\chatappexample\server\node_modules\mongoose\lib\document.js:71:11)
    at EmbeddedDocument [as constructor] (C:\learning\chatappexample\server\node_modules\mongoose\lib\types\embedded.js:41:12)
    at new EmbeddedDocument (C:\learning\chatappexample\server\node_modules\mongoose\lib\schema\documentarray.js:76:17)
    at DocumentArray.SchemaArray.castForQuery (C:\learning\chatappexample\server\node_modules\mongoose\lib\schema\array.js:312:13)
    at DocumentArray.SchemaType.castForQueryWrapper (C:\learning\chatappexample\server\node_modules\mongoose\lib\schematype.js:1185:15)
    at castUpdateVal (C:\learning\chatappexample\server\node_modules\mongoose\lib\helpers\query\castUpdate.js:427:17)
    at walkUpdatePath (C:\learning\chatappexample\server\node_modules\mongoose\lib\helpers\query\castUpdate.js:261:22)
    at castUpdate (C:\learning\chatappexample\server\node_modules\mongoose\lib\helpers\query\castUpdate.js:79:18)
    at model.Query._castUpdate (C:\learning\chatappexample\server\node_modules\mongoose\lib\query.js:4064:10)
    at castDoc (C:\learning\chatappexample\server\node_modules\mongoose\lib\query.js:4092:18)
    at model.Query._updateThunk (C:\learning\chatappexample\server\node_modules\mongoose\lib\query.js:3399:17)
    at model.Query.Query._execUpdate (C:\learning\chatappexample\server\node_modules\mongoose\lib\query.js:3460:23)
    at process.nextTick (C:\learning\chatappexample\server\node_modules\kareem\index.js:369:33)
    at process._tickCallback (internal/process/next_tick.js:61:11)

Sorry solved my bad.

Why do I need to use callbacks so the saved on the database?
An example does not save to database

  Chat.updateOne( { _id: chatdata._id }, { $push: { message: {
      from: data.from,
      type: 'Text',
      text: data.message
    }}
   }, { safe: true, upsert: true })

An example does success save to database

  Chat.updateOne( { _id: chatdata._id }, { $push: { message: {
      from: data.from,
      type: 'Text',
      text: data.message
    }}
   }, { safe: true, upsert: true }, (err, data) => console.log(data))

@mandaputtra you need to actually execute the query. That doesn't happen until you pass a callback, call Query#then(), or call Query#exec(). If you don't want to pass a callback or use then(), use this:

  Chat.updateOne( { _id: chatdata._id }, { $push: { message: {
      from: data.from,
      type: 'Text',
      text: data.message
    }}
   }, { safe: true, upsert: true }).exec()
Was this page helpful?
0 / 5 - 0 ratings