github/copilot-sdk · error · ResponseError

negative_zero

negative_zero

Error message

${context.label} contains negative zero at ${path}; normalize it to 0

What it means

The strict JSON validator rejects -0 because JSON.stringify serializes it as "0", so a journaled -0 would silently come back as 0 after a session resume, breaking the library's lossless replay guarantee. The error includes the path to the offending value.

Solutions

  1. Locate the value via the error's `path` and normalize it: `Object.is(v, -0) ? 0 : v`.
  2. Add `+ value` or `value + 0` normalization at the factory boundary before returning journaled data.
  3. Fix the upstream arithmetic so signed zero is never produced (e.g. use Math.round(Math.abs(x)) * sign).

Example fix

// before
return { delta: Math.round(-0.4) }; // -0
// after
return { delta: Math.round(-0.4) + 0 }; // 0
Defensive patterns

Strategy: validation

Validate before calling

function normalizeNegativeZero(v) {
  if (typeof v === "number") return Object.is(v, -0) ? 0 : v;
  if (Array.isArray(v)) return v.map(normalizeNegativeZero);
  if (v && typeof v === "object") return Object.fromEntries(Object.entries(v).map(([k, x]) => [k, normalizeNegativeZero(x)]));
  return v;
}

Type guard

const isNegativeZero = (v: unknown): boolean => Object.is(v, -0);

Try / catch

try {
  session.runFactory(step);
} catch (e) {
  if (e?.details?.category === "negative_zero") {
    console.error(`Normalize -0 at ${e.details.path} to 0`);
  } else throw e;
}

Prevention

When it happens

Trigger: Returning a factory result or step value equal to -0, typically produced by expressions like -0, 0 * -1, -1 % 0 === -0? (no, but -0 arises from Math.round(-0.4), Math.sign(-0), Object.freeze artifacts, or negating zero).

Common situations: Math.round(-0.4) yielding -0, Math.sign(-0), negating a zero computed elsewhere, deserializing numeric data that contains -0, and clone/copy helpers preserving the signed zero.

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/0e85215425be347a. Report an issue: GitHub.

Appendix: source

Thrown at nodejs/src/session.ts:2321

                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;
        }
        if (
            typeof current === "function" ||
            typeof current === "symbol" ||
            typeof current === "bigint"
        ) {
            throw strictJsonValidationError(
                context,
                "unsupported_type",
                `${context.label} contains a function, symbol, or BigInt at ${path}`,
                path

View on GitHub (pinned to cd8cf15dc3)