Automattic/mongoose · error · CastError
Cast to Double failed for value "${value}" (type ${valueType
Error message
Cast to Double failed for value "${value}" (type ${valueType}) at path "${path}" What it means
SchemaDouble.cast converts failures of the Double caster (lib/cast/double.js) into this CastError. Valid input: null/undefined and empty string (→ null), numbers, BSON Long, strings parsed by BSON's strict `Double.fromString`, and objects whose valueOf()/toString() yields a parseable decimal string. Arrays, plain objects without numeric coercion, and non-decimal strings ('abc') throw.
Source
Thrown at lib/schema/double.js:189
* @param {object} value
* @param {object} model this value is optional
* @api private
*/
SchemaDouble.prototype.cast = function(value) {
let castDouble;
if (typeof this._castFunction === 'function') {
castDouble = this._castFunction;
} else if (typeof this.constructor.cast === 'function') {
castDouble = this.constructor.cast();
} else {
castDouble = SchemaDouble.cast();
}
try {
return castDouble(value);
} catch (error) {
throw new CastError('Double', value, this.path, error, this);
}
};
/*!
* ignore
*/
function handleSingle(val) {
return this.cast(val);
}
const $conditionalHandlers = {
...SchemaType.prototype.$conditionalHandlers,
$gt: handleSingle,
$gte: handleSingle,
$lt: handleSingle,
$lte: handleSingle
};View on GitHub (pinned to 49cdab0136)
Solutions
- Assign plain numbers: `doc.ratio = 1.5`
- Strip/validate strings to decimal format before assigning (regex `/^[+-]?\d+(\.\d+)?$/`)
- Coerce with `Number(v)` at the boundary and check `Number.isNaN`
- For arrays of readings, map to numbers explicitly instead of assigning the array
Example fix
// before
metric.ratio = req.body.ratio; // '1,5' or 'n/a'
// after
const ratio = Number(String(req.body.ratio).replace(',', '.'));
if (Number.isNaN(ratio)) throw new ValidationError('bad ratio');
metric.ratio = ratio; Defensive patterns
Strategy: validation
Validate before calling
function toDouble(v) {
if (v == null || v === '') return null;
if (Array.isArray(v)) throw new Error('array is not a double');
const n = typeof v === 'number' ? v : Number(String(v).replace(',', '.'));
if (Number.isNaN(n)) throw new Error(`not a double: ${v}`);
return n;
}
metric.ratio = toDouble(req.body.ratio); Type guard
function isDoubleLike(v) {
if (v == null || v === '' || typeof v === 'number') return true;
return typeof v === 'string' && !Number.isNaN(Number(v.replace(',', '.')));
} Try / catch
try { doc.ratio = v; } catch (err) { if (err.name === 'CastError' && err.kind === 'Double') { return badRequest(`${err.path} must be a number`); } throw err; } Prevention
- Coerce strings to Number at the boundary
- Never assign arrays to scalar fields
- Validate numeric request fields with zod/joi before they hit models
When it happens
Trigger: `doc.ratio = 'abc'`, `doc.ratio = [1.5]` (arrays explicitly rejected), `doc.ratio = {}`, or an object whose `valueOf()` returns a non-parseable string. Query side: `{ ratio: { $gt: 'n/a' } }`.
Common situations: Mongoose 8's Double type used with un-sanitized string input from forms or spreadsheets; locale-formatted numbers ('1,5'); expecting JS-style loose Number coercion ('5px' works with Number() but Double.fromString rejects it); passing arrays from destructuring mistakes.
Related errors
- Query filter must be an object, got an array ${util.inspect(
- Cast to date failed for value "${value}" (type ${valueType})
- Cast to Decimal128 failed for value "${value}" (type ${value
- Cast to Int32 failed for value "${value}" (type ${valueType}
- Cast to Number failed for value "${value}" (type ${valueType
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/89e0475f6a8d7c72.
Report an issue: GitHub.