{"record":{"id":"d997ccfaded7f0fe","repo":"can1357/oh-my-pi","slug":"label-must-be-a-finite-number","errorCode":null,"errorMessage":"${label} must be a finite number","messagePattern":"(.+?) must be a finite number","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/launch/protocol.ts","lineNumber":182,"sourceCode":"}\n\nfunction optionalString(value: unknown, label: string): string | undefined {\n\tif (value === undefined) return undefined;\n\treturn stringValue(value, label);\n}\n\nfunction optionalRawString(value: unknown, label: string): string | undefined {\n\tif (value === undefined) return undefined;\n\treturn rawString(value, label);\n}\n\nfunction booleanValue(value: unknown, label: string): boolean {\n\tif (typeof value !== \"boolean\") throw new Error(`${label} must be a boolean`);\n\treturn value;\n}\n\nfunction numberValue(value: unknown, label: string): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) throw new Error(`${label} must be a finite number`);\n\treturn value;\n}\n\nfunction optionalNumber(value: unknown, label: string): number | undefined {\n\tif (value === undefined) return undefined;\n\treturn numberValue(value, label);\n}\n\nfunction stringArray(value: unknown, label: string): string[] {\n\tif (!Array.isArray(value)) throw new Error(`${label} must be an array of strings`);\n\tconst result: string[] = [];\n\tfor (const item of value) result.push(rawString(item, `${label} item`));\n\treturn result;\n}\n\nfunction stringRecord(value: unknown, label: string): Record<string, string> {\n\tconst source = record(value, label);\n\tconst result: Record<string, string> = {};","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/launch/protocol.ts#L164-L200","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Identify the field from the label and coerce to a finite number at the producer (Number(value), parseInt)","Replace string numbers in config with unquoted numbers","If the value can legitimately be absent, omit the key so optionalNumber is used","Validate Infinity/NaN before serialization"],"exampleFix":"// before\nparseDaemonSpec({ id: \"d1\", command: [\"srv\"], ready: { timeoutMs: \"5000\", log: \"up\" } })\n// after\nparseDaemonSpec({ id: \"d1\", command: [\"srv\"], ready: { timeoutMs: 5000, log: \"up\" } })","handlingStrategy":"validation","validationCode":"function isFiniteNumber(v: unknown): v is number { return typeof v === \"number\" && Number.isFinite(v); }\nif (!isFiniteNumber(payload.ready?.timeoutMs)) throw new Error(\"ready.timeoutMs must be a finite number\");","typeGuard":"function isFiniteNumber(v: unknown): v is number { return typeof v === \"number\" && Number.isFinite(v); }","tryCatchPattern":"try {\n  const snapshot = parseDaemonSnapshot(raw);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"must be a finite number\")) {\n    // inspect the labeled field; coerce Number(value) and retry or fail fast\n  } else throw err;\n}","preventionTips":["Never quote numeric values in config files","Guard arithmetic that can produce NaN/Infinity before serialization","Use optionalNumber-friendly omission (delete the key) instead of null for absent numbers","Add JSON schema validation with type: number before handing off to the parser"],"tags":["validation","ipc","numbers","type-mismatch"],"backgroundTag":"schema-validation-failed","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}