{"record":{"id":"7114ffa4b2eb5b70","repo":"DefinitelyTyped/DefinitelyTyped","slug":"bad-inc-parameter-value-must-be-a-number","errorCode":null,"errorMessage":"Bad $inc parameter - value must be a number","messagePattern":"Bad \\$inc parameter - value must be a number","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"types/documentdb-server/documentdb-server-tests.ts","lineNumber":521,"sourceCode":"        );\n\n        // If we hit execution bounds - throw an exception.\n        if (!isAccepted) {\n            throw new Error(\"The stored procedure timed out.\");\n        }\n    }\n\n    // Operator implementations.\n    // The $inc operator increments the value of a field by a specified amount.\n    function inc(document: any, update: any) {\n        var fields: string[], i: number;\n\n        if (update.$inc) {\n            fields = Object.keys(update.$inc);\n            for (i = 0; i < fields.length; i++) {\n                if (isNaN(update.$inc[fields[i]])) {\n                    // Validate the field; throw an exception if it is not a number (can't increment by NaN).\n                    throw new Error(\"Bad $inc parameter - value must be a number\");\n                } else if (document[fields[i]]) {\n                    // If the field exists, increment it by the given amount.\n                    document[fields[i]] += update.$inc[fields[i]];\n                } else {\n                    // Otherwise set the field to the given amount.\n                    document[fields[i]] = update.$inc[fields[i]];\n                }\n            }\n        }\n    }\n\n    // The $mul operator multiplies the value of the field by the specified amount.\n    function mul(document: any, update: any) {\n        var fields: string[], i: number;\n\n        if (update.$mul) {\n            fields = Object.keys(update.$mul);\n            for (i = 0; i < fields.length; i++) {","sourceCodeStart":503,"sourceCodeEnd":539,"githubUrl":"https://github.com/DefinitelyTyped/DefinitelyTyped/blob/8f494947aedf1aa8238676d55723ae7f62b7dd15/types/documentdb-server/documentdb-server-tests.ts#L503-L539","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\nconst update = { $inc: { visits: req.body.visits } }; // visits arrives as \"5\"\nclient.executeStoredProcedure(updateSprocLink, [id, update], { partitionKey }, cb);\n\n// after: coerce + validate before sending\nconst visits = Number(req.body.visits);\nif (!Number.isFinite(visits)) return next(new TypeError('visits must be numeric'));\nconst update = { $inc: { visits } };\nclient.executeStoredProcedure(updateSprocLink, [id, update], { partitionKey }, cb);","handlingStrategy":"validation","validationCode":"// Validate the whole update object before invoking the sproc.\nfunction validateInc(update) {\n  if (!update || !update.$inc) return true;\n  return Object.entries(update.$inc).every(([, v]) => Number.isFinite(Number(v)));\n}\nif (!validateInc(update)) throw new TypeError('$inc values must be finite numbers');","typeGuard":"// Type-narrow the $inc operand at the boundary.\ninterface IncOp { $inc?: Record<string, number>; }\nfunction isIncOp(u: unknown): u is IncOp {\n  if (!u || typeof u !== 'object' || !(\"$inc\" in u)) return true;\n  const inc = (u as any).$inc;\n  return inc == null || Object.values(inc).every((v) => typeof v === 'number' && Number.isFinite(v));\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["documentdb-server","stored-procedure","update-operator","inc","validation","nan"],"backgroundTag":null,"analyzedSha":"8f494947aedf1aa8238676d55723ae7f62b7dd15","analyzedAt":"2026-08-12T16:01:38.919Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}