can1357/oh-my-pi · error

${label} must be a finite number

Error message

${label} must be a finite number

What it means

Thrown by numberValue(), which requires a JSON number that is finite (rejects NaN and ±Infinity). Fields like timeouts, ports, and PIDs in daemon specs, snapshots, operations, and RPC results go through it. It prevents non-numeric or non-finite values from entering daemon timing/logic code.

Source

Thrown at packages/coding-agent/src/launch/protocol.ts:182

}

function optionalString(value: unknown, label: string): string | undefined {
	if (value === undefined) return undefined;
	return stringValue(value, label);
}

function optionalRawString(value: unknown, label: string): string | undefined {
	if (value === undefined) return undefined;
	return rawString(value, label);
}

function booleanValue(value: unknown, label: string): boolean {
	if (typeof value !== "boolean") throw new Error(`${label} must be a boolean`);
	return value;
}

function numberValue(value: unknown, label: string): number {
	if (typeof value !== "number" || !Number.isFinite(value)) throw new Error(`${label} must be a finite number`);
	return value;
}

function optionalNumber(value: unknown, label: string): number | undefined {
	if (value === undefined) return undefined;
	return numberValue(value, label);
}

function stringArray(value: unknown, label: string): string[] {
	if (!Array.isArray(value)) throw new Error(`${label} must be an array of strings`);
	const result: string[] = [];
	for (const item of value) result.push(rawString(item, `${label} item`));
	return result;
}

function stringRecord(value: unknown, label: string): Record<string, string> {
	const source = record(value, label);
	const result: Record<string, string> = {};

View on GitHub (pinned to 9690622007)

Solutions

  1. Identify the field from the label and coerce to a finite number at the producer (Number(value), parseInt)
  2. Replace string numbers in config with unquoted numbers
  3. If the value can legitimately be absent, omit the key so optionalNumber is used
  4. Validate Infinity/NaN before serialization

Example fix

// before
parseDaemonSpec({ id: "d1", command: ["srv"], ready: { timeoutMs: "5000", log: "up" } })
// after
parseDaemonSpec({ id: "d1", command: ["srv"], ready: { timeoutMs: 5000, log: "up" } })
Defensive patterns

Strategy: validation

Validate before calling

function isFiniteNumber(v: unknown): v is number { return typeof v === "number" && Number.isFinite(v); }
if (!isFiniteNumber(payload.ready?.timeoutMs)) throw new Error("ready.timeoutMs must be a finite number");

Type guard

function isFiniteNumber(v: unknown): v is number { return typeof v === "number" && Number.isFinite(v); }

Try / catch

try {
  const snapshot = parseDaemonSnapshot(raw);
} catch (err) {
  if (err instanceof Error && err.message.includes("must be a finite number")) {
    // inspect the labeled field; coerce Number(value) and retry or fail fast
  } else throw err;
}

Prevention

When it happens

Trigger: Calling any daemon parse function with a field expected to be a number that is a string ("5000"), null, undefined, NaN, or Infinity — e.g. ready.timeoutMs, timeoutMs, pid, or port fields.

Common situations: Config authored with quoted numbers; JSON.stringify of Infinity/NaN producing null; division or arithmetic upstream producing NaN; missing optional field serialized as null instead of omitted.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/d997ccfaded7f0fe. Report an issue: GitHub.