{"record":{"id":"16dd770f2bcc6873","repo":"Automattic/mongoose","slug":"no-id-found-on-document","errorCode":null,"errorMessage":"No _id found on document!","messagePattern":"No _id found on document!","errorType":"exception","errorClass":"MongooseError","httpStatus":null,"severity":"error","filePath":"lib/model.js","lineNumber":791,"sourceCode":"\n/**\n * Returns a query object\n *\n * @api private\n * @method $__where\n * @memberOf Model\n * @instance\n */\n\nModel.prototype.$__where = function _where(where) {\n  where || (where = {});\n\n  if (!where._id) {\n    where._id = this._doc._id;\n  }\n\n  if (this._doc._id === void 0) {\n    throw new MongooseError('No _id found on document!');\n  }\n\n  return where;\n};\n\n/**\n * Delete this document from the db. Returns a Query instance containing a `deleteOne` operation by this document's `_id`.\n *\n * #### Example:\n *\n *     await product.deleteOne();\n *     await Product.findById(product._id); // null\n *\n * Since `deleteOne()` returns a Query, the `deleteOne()` will **not** execute unless you use either `await`, `.then()`, `.catch()`, or [`.exec()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.exec())\n *\n * #### Example:\n *\n *     product.deleteOne(); // Doesn't do anything","sourceCodeStart":773,"sourceCodeEnd":809,"githubUrl":"https://github.com/Automattic/mongoose/blob/49cdab01366679723b487ecb754b38570f783289/lib/model.js#L773-L809","documentation":"Document-level delete (doc.deleteOne()) builds its filter from the document's _id via $__where; if the in-memory document has no _id the query would match nothing (or be ambiguous), so Mongoose throws 'No _id found on document!'. It means the document object itself lacks _id — schema disabled it, the doc was hydrated from data without one, or _id was unset.","triggerScenarios":"doc.deleteOne() where doc was created as new Model({ name: 'x' }) under a schema with _id: false (or a String _id never assigned), or hydrated/cloned from a cached object that had no _id, or doc._id was deleted before the call.","commonSituations":"Reusing _id: false schemas for top-level docs; deserializing session/cache objects back into documents; test fixtures omitting _id; deleting a doc whose save earlier failed with 'document must have an _id before saving'.","solutions":["Delete by explicit filter on a unique natural key instead: Model.deleteOne({ slug: doc.slug })","Hydrate documents from the database (with _id) before calling doc.deleteOne()","Ensure the schema generates or requires _id so every loaded doc carries one"],"exampleFix":"// before\nconst doc = new TempModel({ jobId }); // schema has _id: false\nawait doc.deleteOne(); // throws: No _id found on document!\n\n// after\nawait TempModel.deleteOne({ jobId });","handlingStrategy":"validation","validationCode":"// Only attempt document deletion when an _id is present\nasync function deleteDoc(doc) {\n  if (doc._id == null) {\n    return doc.constructor.deleteOne({ jobId: doc.jobId }); // unique natural key\n  }\n  return doc.deleteOne();\n}","typeGuard":"const hasDocumentId = (doc) => doc?._id !== undefined && doc?._id !== null;","tryCatchPattern":"try {\n  await doc.deleteOne();\n} catch (err) {\n  if (err instanceof mongoose.MongooseError && /No _id found/.test(err.message)) {\n    // fall back to Model.deleteOne with a unique filter\n  } else throw err;\n}","preventionTips":["Ensure documents you intend to delete were hydrated from the database (with _id)","Give every top-level schema an _id (default ObjectId or a defaulted custom type)","Prefer Model.deleteOne(filter) for keys without _id rather than document deletion"],"tags":["mongoose","delete","id","document"],"backgroundTag":"missing-document-id","analyzedSha":"49cdab01366679723b487ecb754b38570f783289","analyzedAt":"2026-08-21T22:54:00.882Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}