Automattic/mongoose · error · CastError
Cast to [${e.kind}] failed for value "${value}" (type ${valu
Error message
Cast to [${e.kind}] failed for value "${value}" (type ${valueType}) at path "${path}.${i}" What it means
While casting each element of an array assigned to a document (set/save), the embedded schema type's caster threw; mongoose rewraps it as a CastError with the embedded kind in brackets, the whole value, and the failing index appended to the path (path.i). The [Kind], value, and index pinpoint the bad element.
Source
Thrown at lib/schema/array.js:407
// skip if possible.
if (isMongooseArray) {
if (options.arrayPath != null) {
opts.arrayPathIndex = i;
} else if (caster._arrayParentPath != null) {
opts.arrayPathIndex = i;
}
}
if (options.hydratedPopulatedDocs) {
opts.hydratedPopulatedDocs = options.hydratedPopulatedDocs;
}
if (options.virtuals) {
opts.virtuals = options.virtuals;
}
rawValue[i] = caster.applySetters(rawValue[i], doc, init, void 0, opts);
}
} catch (e) {
// rethrow
throw new CastError('[' + e.kind + ']', util.inspect(value), this.path + '.' + i, e, this);
}
}
return value;
}
const castNonArraysOption = this.options.castNonArrays ?? SchemaArray.options.castNonArrays;
if (init || castNonArraysOption) {
// gh-2442: if we're loading this from the db and its not an array, mark
// the whole array as modified.
if (doc && init) {
doc.markModified(this.path);
}
return this.cast([value], doc, init);
}
throw new CastError('Array', util.inspect(value), this.path, null, this);
};View on GitHub (pinned to 49cdab0136)
Solutions
- Fix or filter the element at the reported index - path.i names it exactly.
- Validate arrays at the API boundary (zod/joi) before assignment, or enable runValidators on the assignment path.
- Only if intentional, loosen the failing element type (e.g. store as [Mixed]) rather than weakening the whole path.
Example fix
// before
doc.ids = req.body.ids; // ['507f1f77bcf86cd799439011', 'not-an-id'] -> CastError [ObjectId] at ids.1
// after
const ok = req.body.ids.every(v => /^[0-9a-fA-F]{24}$/.test(v));
if (!ok) return res.status(400).json({ error: 'invalid ids' });
doc.ids = req.body.ids; Defensive patterns
Strategy: try-catch
Validate before calling
const isValidObjectId = (v) => v == null || /^[0-9a-fA-F]{24}$/.test(v) || v instanceof mongoose.Types.ObjectId;
const allElementsCastable = (arr) => Array.isArray(arr) && arr.every(isValidObjectId);
if (!allElementsCastable(req.body.ids)) return res.status(400).json({ error: 'bad ids' });
doc.ids = req.body.ids; Try / catch
try {
doc.arr = input;
await doc.save();
} catch (err) {
if (err instanceof mongoose.Error.CastError && err.path?.startsWith('arr.')) {
// err.path names the failing element (e.g. arr.1), err.value the bad input
return res.status(400).json({ error: `invalid value at ${err.path}` });
}
throw err;
} Prevention
- Map request payloads through runtime validation (zod/joi) so cast errors never reach mongoose.
- Log err.path and err.value from CastError - they pinpoint the failing index immediately.
- For ObjectId arrays, pre-check 24-hex format before assignment.
When it happens
Trigger: `doc.tags = ['ok', 'xyz']` with `tags: [Number]`; assigning strings that are not 24-hex to a `[ObjectId]` path; `[Date]` with element '32/13/2020'; nested arrays where an inner element fails to cast.
Common situations: Unvalidated request bodies (strings from forms/JSON) written straight to typed arrays; upstream APIs changing element types; mixed-quality imported data.
Related errors
- Cast to Array failed for value "${value}" (type ${valueType}
- Can't use ${$conditional} with Array.
- Cast to BigInt failed for value "${value}" (type ${valueType
- Cast to Boolean failed for value "${value}" (type ${valueTyp
- Aggregate.prototype.exec() no longer accepts a callback
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/d426f038d4b96d79.
Report an issue: GitHub.