DefinitelyTyped/DefinitelyTyped · error · Error
Bad $inc parameter - value must be a number
Error message
Bad $inc parameter - value must be a number
What it means
Thrown by the $inc handler in updateDocument. For each field in update.$inc the sproc runs isNaN(update.$inc[field]); if the value coerces to NaN (non-numeric), it aborts with this message before touching the document. isNaN is applied loosely, so null/undefined/""/"abc"/objects all fail; numeric strings pass (isNaN("5") is false), which is intentional DocumentDB-sample behavior.
Source
Thrown at types/documentdb-server/documentdb-server-tests.ts:521
);
// If we hit execution bounds - throw an exception.
if (!isAccepted) {
throw new Error("The stored procedure timed out.");
}
}
// Operator implementations.
// The $inc operator increments the value of a field by a specified amount.
function inc(document: any, update: any) {
var fields: string[], i: number;
if (update.$inc) {
fields = Object.keys(update.$inc);
for (i = 0; i < fields.length; i++) {
if (isNaN(update.$inc[fields[i]])) {
// Validate the field; throw an exception if it is not a number (can't increment by NaN).
throw new Error("Bad $inc parameter - value must be a number");
} else if (document[fields[i]]) {
// If the field exists, increment it by the given amount.
document[fields[i]] += update.$inc[fields[i]];
} else {
// Otherwise set the field to the given amount.
document[fields[i]] = update.$inc[fields[i]];
}
}
}
}
// The $mul operator multiplies the value of the field by the specified amount.
function mul(document: any, update: any) {
var fields: string[], i: number;
if (update.$mul) {
fields = Object.keys(update.$mul);
for (i = 0; i < fields.length; i++) {View on GitHub (pinned to 8f494947ae)
Solutions
- Coerce $inc values to numbers on the client before invoking the sproc: Number(v) and check Number.isFinite.
- If consuming MongoDB Extended JSON, unwrap {$numberInt/$numberDouble} to plain numbers first.
- Add a unit test that builds the update object with explicit numeric literals.
- Validate the whole update spec with a JSON-schema that requires $inc.* to be number.
Example fix
// before
const update = { $inc: { visits: req.body.visits } }; // visits arrives as "5"
client.executeStoredProcedure(updateSprocLink, [id, update], { partitionKey }, cb);
// after: coerce + validate before sending
const visits = Number(req.body.visits);
if (!Number.isFinite(visits)) return next(new TypeError('visits must be numeric'));
const update = { $inc: { visits } };
client.executeStoredProcedure(updateSprocLink, [id, update], { partitionKey }, cb); Defensive patterns
Strategy: validation
Validate before calling
// Validate the whole update object before invoking the sproc.
function validateInc(update) {
if (!update || !update.$inc) return true;
return Object.entries(update.$inc).every(([, v]) => Number.isFinite(Number(v)));
}
if (!validateInc(update)) throw new TypeError('$inc values must be finite numbers'); Type guard
// Type-narrow the $inc operand at the boundary.
interface IncOp { $inc?: Record<string, number>; }
function isIncOp(u: unknown): u is IncOp {
if (!u || typeof u !== 'object' || !("$inc" in u)) return true;
const inc = (u as any).$inc;
return inc == null || Object.values(inc).every((v) => typeof v === 'number' && Number.isFinite(v));
} Prevention
- Coerce all $inc operands to Number() on the client and reject non-finite values.
- Unwrap MongoDB Extended JSON numeric wrappers before sending to this sproc.
- Build $inc patches from numeric literals, never from raw user strings.
- Add a unit test that feeds a non-numeric value and asserts the client rejects before the call.
When it happens
Trigger: Passing an update whose $inc maps a field to a non-numeric value: update = { $inc: { count: "five" } }, { $inc: { count: null } }, { $inc: { count: undefined } }, or { $inc: { count: { $numberInt: 5 } } } (MongoDB Extended JSON forms are not unwrapped here).
Common situations: Serializing updates from a form/API without coercing types; mixing MongoDB driver conventions (e.g., wrapped numeric types) with this Cosmos sproc; passing a value that came back from another query as a string.
Related errors
- Bad $mul parameter - value must be a number
- Bad $rename parameter: The new field name must differ from t
- Bad $addToSet parameter - field in document must be an array
- Bad $pop parameter - field in document must be an array.
- Bad $push parameter - field in document must be an array.
AI-assisted analysis of DefinitelyTyped/DefinitelyTyped@8f494947ae (2026-08-12).
Data as JSON: /api/errors/7114ffa4b2eb5b70.
Report an issue: GitHub.