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

  1. Find the exact location via the `path` field in error details and fix the computation producing NaN/Infinity.
  2. Guard the value before returning: replace non-finite numbers with null, 0, or a string sentinel.
  3. 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

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)