{"record":{"id":"a03dd598091970b2","repo":"github/copilot-sdk","slug":"non-finite-number","errorCode":"non_finite_number","errorMessage":"${context.label} contains a non-finite number at ${path}","messagePattern":"(.+?) contains a non-finite number at (.+?)","errorType":"validation","errorClass":"ResponseError","httpStatus":null,"severity":"error","filePath":"nodejs/src/session.ts","lineNumber":2311,"sourceCode":"\n    const visit = (current: unknown, path: string, allowUndefined: boolean): void => {\n        if (current === undefined) {\n            if (allowUndefined) {\n                return;\n            }\n            throw strictJsonValidationError(\n                context,\n                \"nested_undefined\",\n                `${context.label} contains nested undefined at ${path}`,\n                path\n            );\n        }\n        if (current === null || typeof current === \"boolean\" || typeof current === \"string\") {\n            return;\n        }\n        if (typeof current === \"number\") {\n            if (!Number.isFinite(current)) {\n                throw strictJsonValidationError(\n                    context,\n                    \"non_finite_number\",\n                    `${context.label} contains a non-finite number at ${path}`,\n                    path\n                );\n            }\n            // JSON serializes -0 as \"0\", so a journaled -0 would come back as 0\n            // after a resume and break the lossless replay guarantee.\n            if (Object.is(current, -0)) {\n                throw strictJsonValidationError(\n                    context,\n                    \"negative_zero\",\n                    `${context.label} contains negative zero at ${path}; normalize it to 0`,\n                    path\n                );\n            }\n            return;\n        }","sourceCodeStart":2293,"sourceCodeEnd":2329,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/nodejs/src/session.ts#L2293-L2329","documentation":"The session's strict JSON validator (assertStrictJson) rejects any value destined for the journal — a factory result or factory step — that contains NaN, Infinity, or -Infinity. JSON has no representation for these numbers, so journaling them would corrupt lossless replay after a resume. The error carries the JSON path of the offending number.","triggerScenarios":"Returning a factory result or emitting a factory step value that contains NaN, Infinity, or -Infinity at any nesting depth, e.g. result of a division by zero, Math.log(-1), parseInt on a non-numeric string, or a computed metric that overflowed to Infinity.","commonSituations":"Dividing by a zero-sized denominator (total bytes, duration), uninitialized accumulator fields defaulting to NaN, Math operations on invalid input, parsing user numeric input without validation, and float overflow in aggregation code.","solutions":["Find the exact location via the `path` field in error details and fix the computation producing NaN/Infinity.","Guard the value before returning: replace non-finite numbers with null, 0, or a string sentinel.","Validate factory outputs with a recursive isFinite check before returning them from the factory."],"exampleFix":"// before\nconst ratio = bytes / duration; // Infinity when duration === 0\nreturn { ratio };\n// after\nconst ratio = duration === 0 || !Number.isFinite(bytes / duration) ? null : bytes / duration;\nreturn { ratio };","handlingStrategy":"validation","validationCode":"function assertFiniteNumbers(value, path = \"$\") {\n  if (typeof value === \"number\") {\n    if (!Number.isFinite(value)) throw new Error(`Non-finite number at ${path}`);\n  } else if (Array.isArray(value)) {\n    value.forEach((v, i) => assertFiniteNumbers(v, `${path}[${i}]`));\n  } else if (value && typeof value === \"object\") {\n    for (const [k, v] of Object.entries(value)) assertFiniteNumbers(v, `${path}.${k}`);\n  }\n}","typeGuard":"const isFiniteNumber = (v: unknown): v is number => typeof v === \"number\" && Number.isFinite(v);","tryCatchPattern":"try {\n  session.runFactory(step);\n} catch (e) {\n  if (e?.details?.category === \"non_finite_number\") {\n    console.error(`Fix NaN/Infinity at ${e.details.path}`);\n  } else throw e;\n}","preventionTips":["Guard divisions: check denominators for 0 before dividing.","Default numeric fields with ?? 0 and validate parsed numbers with Number.isFinite.","Run assertFiniteNumbers on factory outputs in tests."],"tags":["json","validation","numbers","factory-result"],"backgroundTag":"json-serialization-failed","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}