{"record":{"id":"def27e67e586017a","repo":"Automattic/mongoose","slug":"parameter-obj-to-document-must-be-an-object-g","errorCode":null,"errorMessage":"Parameter \"obj\" to Document() must be an object, got \"${obj}\" (type ${typeof obj})","messagePattern":"Parameter \"obj\" to Document\\(\\) must be an object, got \"(.+?)\" \\(type (.+?)\\)","errorType":"exception","errorClass":"ObjectParameterError","httpStatus":null,"severity":"error","filePath":"lib/document.js","lineNumber":126,"sourceCode":"    fields = options;\n    skipId = options.skipId;\n  }\n\n  // Avoid setting `isNew` to `true`, because it is `true` by default\n  if (options.isNew != null && options.isNew !== true) {\n    this.$isNew = options.isNew;\n  }\n\n  if (options.priorDoc != null) {\n    this.$__.priorDoc = options.priorDoc;\n  }\n\n  if (skipId) {\n    this.$__.skipId = skipId;\n  }\n\n  if (obj != null && typeof obj !== 'object') {\n    throw new ObjectParameterError(obj, 'obj', 'Document');\n  }\n\n  let defaults = true;\n  if (options.defaults !== undefined) {\n    this.$__.defaults = options.defaults;\n    defaults = options.defaults;\n  }\n\n  const schema = this.$__schema;\n\n  if (typeof fields === 'boolean' || fields === 'throw') {\n    if (fields !== true) {\n      this.$__.strictMode = fields;\n    }\n    fields = undefined;\n  } else if (options.strict !== undefined) {\n    this.$__.strictMode = options.strict;\n  } else if (schema.options.strict !== true) {","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/Automattic/mongoose/blob/49cdab01366679723b487ecb754b38570f783289/lib/document.js#L108-L144","documentation":"The Document constructor validates that its first argument is an object (or null/undefined) before applying paths and defaults. Passing any primitive — string, number, boolean — throws ObjectParameterError, and the message embeds the received value and its typeof so the offending input is identifiable.","triggerScenarios":"new MyModel('foo'), new MyModel(42), or new MyModel(JSON.stringify(data)) — constructing a document from a non-object value.","commonSituations":"Request bodies arriving as strings because of missing express.json()/wrong Content-Type; a failed JSON.parse upstream; CSV/Excel importers that end up passing strings; forwarding a querystring like 'a=1&b=2'.","solutions":["Validate the payload shape before constructing: if (typeof body === 'string') body = JSON.parse(body)","Fix body parsing: register a JSON body parser and send Content-Type: application/json from clients","Null and undefined are accepted — pass undefined rather than an empty string when there is no data"],"exampleFix":"// before\n// client sent text/plain, express.json() not configured → req.body is a string\nconst user = new User(req.body);\n\n// after\napp.use(express.json()); // and client sends Content-Type: application/json\nconst user = new User(req.body);","handlingStrategy":"type-guard","validationCode":"const isRecord = (v) => v != null && typeof v === 'object' && !Array.isArray(v);\nif (!isRecord(payload)) {\n  throw new TypeError('payload must be an object, got ' + typeof payload);\n}\nconst doc = new MyModel(payload);","typeGuard":"const isPlainishObject = (v) =>\n  v != null && typeof v === 'object' && !Array.isArray(v) && v.constructor === Object;","tryCatchPattern":"try {\n  doc = new MyModel(input);\n} catch (err) {\n  if (err.name === 'ObjectParameterError') {\n    return res.status(400).json({ error: 'body must be a JSON object' });\n  }\n  throw err;\n}","preventionTips":["Validate request bodies at the boundary (schema/DTO validation) before touching models","Configure JSON body parsing and require Content-Type: application/json from clients","When input may be JSON text, parse and re-validate before constructing documents"],"tags":["document","constructor","type-validation","objectparametererror","mongoose"],"backgroundTag":"invalid-argument-type","analyzedSha":"49cdab01366679723b487ecb754b38570f783289","analyzedAt":"2026-08-21T22:54:00.882Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}