github/copilot-sdk · error · ResponseError
non_finite_number
non_finite_number
Error message
${context.label} contains a non-finite number at ${path} What it means
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.
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.
Example fix
// before
const ratio = bytes / duration; // Infinity when duration === 0
return { ratio };
// after
const ratio = duration === 0 || !Number.isFinite(bytes / duration) ? null : bytes / duration;
return { ratio }; Defensive patterns
Strategy: validation
Validate before calling
function assertFiniteNumbers(value, path = "$") {
if (typeof value === "number") {
if (!Number.isFinite(value)) throw new Error(`Non-finite number at ${path}`);
} else if (Array.isArray(value)) {
value.forEach((v, i) => assertFiniteNumbers(v, `${path}[${i}]`));
} else if (value && typeof value === "object") {
for (const [k, v] of Object.entries(value)) assertFiniteNumbers(v, `${path}.${k}`);
}
} Type guard
const isFiniteNumber = (v: unknown): v is number => typeof v === "number" && Number.isFinite(v);
Try / catch
try {
session.runFactory(step);
} catch (e) {
if (e?.details?.category === "non_finite_number") {
console.error(`Fix NaN/Infinity at ${e.details.path}`);
} else throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "JSON serialization failed", "not JSON serializable", "Failed to serialize": why JSON marshaling errors happen and how to fix them — this error's family across 46 libraries.
Related errors
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/a03dd598091970b2.
Report an issue: GitHub.
Appendix: source
Thrown at nodejs/src/session.ts:2311
const visit = (current: unknown, path: string, allowUndefined: boolean): void => {
if (current === undefined) {
if (allowUndefined) {
return;
}
throw strictJsonValidationError(
context,
"nested_undefined",
`${context.label} contains nested undefined at ${path}`,
path
);
}
if (current === null || typeof current === "boolean" || typeof current === "string") {
return;
}
if (typeof current === "number") {
if (!Number.isFinite(current)) {
throw strictJsonValidationError(
context,
"non_finite_number",
`${context.label} contains a non-finite number at ${path}`,
path
);
}
// JSON serializes -0 as "0", so a journaled -0 would come back as 0
// after a resume and break the lossless replay guarantee.
if (Object.is(current, -0)) {
throw strictJsonValidationError(
context,
"negative_zero",
`${context.label} contains negative zero at ${path}; normalize it to 0`,
path
);
}
return;
}View on GitHub (pinned to cd8cf15dc3)