Automattic/mongoose · error · CastError
Cast to embedded failed for value "${value}" (type ${valueTy
Error message
Cast to embedded failed for value "${value}" (type ${valueType}) at path "${path}" What it means
While casting each element of a document array, Mongoose constructs a subdocument (`new Constructor(element, ...)`) and wraps any construction failure as `CastError: embedded` pointing at the array path. So one element of your subdocument array could not be turned into a subdocument: typically a primitive element (string/number/array) where a plain object is required, or an element whose own nested casting threw during subdocument creation.
Source
Thrown at lib/schema/documentArray.js:492
if (typeof prev?.id === 'function') {
subdoc = prev.id(rawArray[i]._id);
}
if (prev && subdoc && utils.deepEqual(subdoc.toObject(_toObjectOptions), rawArray[i])) {
// handle resetting doc with existing id and same data
subdoc.set(rawArray[i]);
// if set() is hooked it will have no return value
// see gh-746
rawArray[i] = subdoc;
} else {
try {
subdoc = new Constructor(rawArray[i], value, undefined,
undefined, i);
// if set() is hooked it will have no return value
// see gh-746
rawArray[i] = subdoc;
} catch (error) {
throw new CastError('embedded', rawArray[i],
value[arrayPathSymbol], error, this);
}
}
}
}
}
return value;
};
/*!
* ignore
*/
SchemaDocumentArray.prototype.clone = function() {
const options = Object.assign({}, this.options);
const schematype = new this.constructor(
this.path,View on GitHub (pinned to 49cdab0136)
Solutions
- Inspect `err.reason` on the CastError — it carries the underlying error and tells you which element shape failed
- Filter/normalize to plain objects before assignment: `arr.filter(v => utils.isPOJO(v))` or map primitives into `{ value: v }`
- Validate each row against the subschema (validateSync on a scratch document, or ajv) before bulk-inserting
- Add per-element schema validation (e.g. `validate: { validator: v => v != null && typeof v === 'object' }`) to fail with a clearer message
Example fix
// before
doc.items = importedRows; // some rows are plain strings
// after
doc.items = importedRows
.filter(r => r && typeof r === 'object' && !Array.isArray(r))
.map(r => ({ name: String(r.name ?? '') })); Defensive patterns
Strategy: validation
Validate before calling
function sanitizeDocArray(rows) {
return (Array.isArray(rows) ? rows : []).filter(
r => r != null && typeof r === 'object' && !Array.isArray(r)
);
}
doc.items = sanitizeDocArray(importedRows); Type guard
function isPlainObjectRow(v) {
return v != null && typeof v === 'object' && !Array.isArray(v) && !(v instanceof Date) && !Buffer.isBuffer(v);
} Try / catch
try { doc.items = rows; } catch (err) { if (err.name === 'CastError' && err.kind === 'embedded') { console.error('element failed:', err.reason?.message); return badRequest(`invalid element in ${err.path}`); } throw err; } Prevention
- Filter imports to plain-object rows before assigning
- Read err.reason — it names the underlying failure
- Add per-element validators that reject primitives with clear messages
When it happens
Trigger: `doc.items = [{ name: 'ok' }, 'oops']` — array elements that are strings, numbers, or nested arrays instead of plain objects; update operations pushing malformed values (`$push: { items: 'oops' }`); import pipelines feeding mixed rows. The original failure is preserved on the error's `reason` property (and `originalError` fields), which names the real cause.
Common situations: CSV/JSON imports where some rows are scalars or null-ish sentinels; APIs returning heterogeneous arrays; mapping over unvalidated external data into embedded arrays; spread operator bugs that flatten objects into unexpected shapes.
Related errors
- Cast to DocumentArray failed for value "${value}" (type ${va
- Tried to set nested object field `${path}` to ${typeDescript
- Cast to Embedded failed for value "${value}" (type ${valueTy
- Aggregate.prototype.exec() no longer accepts a callback
- Query filter must be an object, got an array ${util.inspect(
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/58314ce926bb5981.
Report an issue: GitHub.