{"record":{"id":"89ac1ff4bbd8c1af","repo":"Automattic/mongoose","slug":"parameter-doc-to-insertone-must-be-an-object","errorCode":null,"errorMessage":"Parameter \"doc\" to insertOne() must be an object, got \"${doc}\" (type ${typeof doc})","messagePattern":"Parameter \"doc\" to insertOne\\(\\) must be an object, got \"(.+?)\" \\(type (.+?)\\)","errorType":"exception","errorClass":"ObjectParameterError","httpStatus":null,"severity":"error","filePath":"lib/model.js","lineNumber":2878,"sourceCode":" *\n *     // Insert one new `Character` document\n *     const character = await Character.insertOne({ name: 'Jean-Luc Picard' });\n *     character.name; // 'Jean-Luc Picard'\n *\n *     // Create a new character within a transaction.\n *     await Character.insertOne({ name: 'Jean-Luc Picard' }, { session });\n *\n * @param {object|Document} doc Document to insert, as a POJO or Mongoose document\n * @param {object} [options] Options passed down to `save()`.\n * @return {Promise<Document>} resolves to the saved document\n * @api public\n */\n\nModel.insertOne = async function insertOne(doc, options) {\n  _checkContext(this, 'insertOne');\n\n  if (doc == null || typeof doc !== 'object') {\n    throw new ObjectParameterError(doc, 'doc', 'insertOne');\n  }\n\n  const discriminatorKey = this.schema.options.discriminatorKey;\n  const Model = this.discriminators && doc[discriminatorKey] != null ?\n    this.discriminators[doc[discriminatorKey]] || getDiscriminatorByValue(this.discriminators, doc[discriminatorKey]) :\n    this;\n  if (Model == null) {\n    throw new MongooseError(\n      `Discriminator \"${doc[discriminatorKey]}\" not found for model \"${this.modelName}\"`\n    );\n  }\n  if (!(doc instanceof Model)) {\n    doc = new Model(doc);\n  }\n\n  return await doc.$save(options);\n};\n","sourceCodeStart":2860,"sourceCodeEnd":2896,"githubUrl":"https://github.com/Automattic/mongoose/blob/49cdab01366679723b487ecb754b38570f783289/lib/model.js#L2860-L2896","documentation":"Model.insertOne() requires its first argument to be a non-null object (POJO or Mongoose Document). The guard `doc == null || typeof doc !== 'object'` throws ObjectParameterError, whose message embeds the received value and its typeof. Note the check happens before discriminator resolution and before any casting, so nothing reaches the database.","triggerScenarios":"Model.insertOne('foo'), insertOne(42), insertOne(null), or insertOne(undefined). Classic source: forgetting JSON.parse on a request body or queue message, so a JSON string is passed instead of an object.","commonSituations":"Passing unparsed JSON strings from HTTP bodies, Redis/Kafka messages, or env vars; passing an id instead of a document; default parameters that evaluate to undefined when an upstream field is missing.","solutions":["Pass a plain object or document: await Model.insertOne({ name: 'x' })","If the input may be a JSON string, parse it first: typeof doc === 'string' ? JSON.parse(doc) : doc","Validate at the trust boundary (route handler / message consumer) that the payload is an object before forwarding to insertOne","In TypeScript, type the parameter so the compiler rejects string/number/null"],"exampleFix":"// before\nconst doc = await req.redis.get('user'); // returns a JSON string\nawait User.insertOne(doc); // throws: must be an object, got \"{...}\" (type string)\n\n// after\nconst raw = await req.redis.get('user');\nawait User.insertOne(JSON.parse(raw));","handlingStrategy":"type-guard","validationCode":"if (doc == null || typeof doc !== 'object') {\n  throw new TypeError(`insertOne: expected object, got ${typeof doc}`);\n}\nawait Model.insertOne(doc);","typeGuard":"function isInsertableDoc(v) {\n  return v != null && typeof v === 'object' && !Array.isArray(v);\n}\n// TypeScript:\n// const isInsertableDoc = (v: unknown): v is Record<string, unknown> | mongoose.Document =>\n//   v != null && typeof v === 'object' && !Array.isArray(v);\nif (!isInsertableDoc(doc)) throw new TypeError('insertOne: doc must be an object');\nawait Model.insertOne(doc);","tryCatchPattern":"try {\n  await Model.insertOne(payload);\n} catch (err) {\n  if (err.name === 'ObjectParameterError') { /* upstream sent a non-object (e.g. unparsed JSON) */ }\n  else throw err;\n}","preventionTips":["Parse JSON at the boundary and type the parsed value before passing it on","Validate request bodies with a schema validator (zod/joi) that enforces object types","Unit-test message consumers with raw string payloads to catch missing JSON.parse"],"tags":["mongoose","insertone","type-validation","invalid-argument","json-parse"],"backgroundTag":"invalid-argument-type","analyzedSha":"49cdab01366679723b487ecb754b38570f783289","analyzedAt":"2026-08-21T22:54:00.882Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}