Automattic/mongoose · error · MongooseError
No _id found on document!
Error message
No _id found on document!
What it means
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.
Source
Thrown at lib/model.js:791
/**
* Returns a query object
*
* @api private
* @method $__where
* @memberOf Model
* @instance
*/
Model.prototype.$__where = function _where(where) {
where || (where = {});
if (!where._id) {
where._id = this._doc._id;
}
if (this._doc._id === void 0) {
throw new MongooseError('No _id found on document!');
}
return where;
};
/**
* Delete this document from the db. Returns a Query instance containing a `deleteOne` operation by this document's `_id`.
*
* #### Example:
*
* await product.deleteOne();
* await Product.findById(product._id); // null
*
* 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())
*
* #### Example:
*
* product.deleteOne(); // Doesn't do anythingView on GitHub (pinned to 49cdab0136)
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
Example fix
// before
const doc = new TempModel({ jobId }); // schema has _id: false
await doc.deleteOne(); // throws: No _id found on document!
// after
await TempModel.deleteOne({ jobId }); Defensive patterns
Strategy: validation
Validate before calling
// Only attempt document deletion when an _id is present
async function deleteDoc(doc) {
if (doc._id == null) {
return doc.constructor.deleteOne({ jobId: doc.jobId }); // unique natural key
}
return doc.deleteOne();
} Type guard
const hasDocumentId = (doc) => doc?._id !== undefined && doc?._id !== null;
Try / catch
try {
await doc.deleteOne();
} catch (err) {
if (err instanceof mongoose.MongooseError && /No _id found/.test(err.message)) {
// fall back to Model.deleteOne with a unique filter
} else throw err;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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'.
Related errors
- Aggregate `near()` argument must have a `near` property
- Aggregate `near()` argument has invalid coordinates, got "${
- Parameter "obj" to Document() must be an object, got "${obj}
- Parameter "doc" to init() must be an object, got "${doc}" (t
- Tried to set nested object field `${path}` to ${typeDescript
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/16dd770f2bcc6873.
Report an issue: GitHub.