Automattic/mongoose · error · CastError

Cast to Int32 failed for value "${value}" (type ${valueType}

Error message

Cast to Int32 failed for value "${value}" (type ${valueType}) at path "${path}"

What it means

SchemaInt32.cast converts failures of the Int32 caster (lib/cast/int32.js) into this CastError. Valid input: null/undefined, empty string (→ null), BSON Long, and anything Number() coerces to an integer within [-2147483648, 2147483647]. Arrays, non-integer values (1.5), and out-of-range integers (3000000000, millisecond timestamps) throw.

Source

Thrown at lib/schema/int32.js:193

 * @param {object} value
 * @param {object} model this value is optional
 * @api private
 */

SchemaInt32.prototype.cast = function(value) {
  let castInt32;
  if (typeof this._castFunction === 'function') {
    castInt32 = this._castFunction;
  } else if (typeof this.constructor.cast === 'function') {
    castInt32 = this.constructor.cast();
  } else {
    castInt32 = SchemaInt32.cast();
  }

  try {
    return castInt32(value);
  } catch (error) {
    throw new CastError('Int32', value, this.path, error, this);
  }
};

/*!
 * ignore
 */

const $conditionalHandlers = {
  ...SchemaType.prototype.$conditionalHandlers,
  $gt: handleSingle,
  $gte: handleSingle,
  $lt: handleSingle,
  $lte: handleSingle,
  $bitsAllClear: handleBitwiseOperator,
  $bitsAnyClear: handleBitwiseOperator,
  $bitsAllSet: handleBitwiseOperator,
  $bitsAnySet: handleBitwiseOperator
};

View on GitHub (pinned to 49cdab0136)

Solutions

  1. Use `mongoose.Schema.Types.Long` or plain `Number` for values that can exceed ±2^31; Int32 is only for guaranteed-small integers
  2. Round before assigning: `doc.count = Math.trunc(v)` and range-check the result
  3. Validate at the boundary: `Number.isInteger(v) && v >= -2147483648 && v <= 2147483647`
  4. Store timestamps as `Schema.Types.Date` instead of numeric epochs

Example fix

// before
event.ts = { type: mongoose.Schema.Types.Int32 }; // then: event.ts = Date.now();

// after
event.ts = { type: Date }; // or Schema.Types.Long for epoch millis
event.ts = Date.now();
Defensive patterns

Strategy: type-guard

Validate before calling

const INT32_MIN = -0x80000000, INT32_MAX = 0x7FFFFFFF;
function isInt32(v) {
  if (v == null || v === '') return true;
  if (Array.isArray(v)) return false;
  const n = typeof v === 'number' ? v : Number(v);
  return Number.isInteger(n) && n >= INT32_MIN && n <= INT32_MAX;
}
if (!isInt32(req.body.count)) throw new Error('count must be a 32-bit integer');

Type guard

function isInt32Value(v) {
  return Number.isInteger(v) && v >= -0x80000000 && v <= 0x7FFFFFFF;
}

Try / catch

try { doc.count = v; } catch (err) { if (err.name === 'CastError' && err.kind === 'Int32') { return badRequest(`${err.path} must be an integer in [-2147483648, 2147483647]`); } throw err; }

Prevention

When it happens

Trigger: `doc.count = 1.5` (non-integer), `doc.count = 3000000000` (exceeds 2^31-1), `doc.count = [1]` (array), `doc.count = 'abc'`, or a Long larger than Int32 range. Query side: `{ count: { $gt: 'big' } }`.

Common situations: Counters and view stats overflowing Int32; Date.now() millisecond timestamps stored in an Int32 path (they need Long or Number); user input with decimals; migrating a Number path to Int32 while existing data exceeds the range; negative overflow from signed math.

Related errors


AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21). Data as JSON: /api/errors/97958d76fcf56dce. Report an issue: GitHub.