{"record":{"id":"3b0823e6b20ccd69","repo":"can1357/oh-my-pi","slug":"unknown-readiness-condition-string-item","errorCode":null,"errorMessage":"Unknown readiness condition: ${String(item)}","messagePattern":"Unknown readiness condition: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/launch/protocol.ts","lineNumber":229,"sourceCode":"\nfunction restartPolicy(value: unknown): DaemonRestartPolicy {\n\tconst policy = stringValue(value, \"restart policy\");\n\tif (policy === \"no\" || policy === \"on-failure\" || policy === \"always\") return policy;\n\tthrow new Error(`Unknown restart policy: ${policy}`);\n}\n\nfunction daemonSignal(value: unknown): DaemonSignal {\n\tconst signal = stringValue(value, \"signal\");\n\tif (signal === \"SIGINT\" || signal === \"SIGTERM\" || signal === \"SIGHUP\") return signal;\n\tif (signal === \"SIGQUIT\" || signal === \"SIGKILL\") return signal;\n\tthrow new Error(`Unknown daemon signal: ${signal}`);\n}\n\nfunction readyPendingList(value: unknown): (\"log\" | \"port\")[] {\n\tif (!Array.isArray(value)) throw new Error(\"daemon.readyPending must be an array\");\n\tconst result: (\"log\" | \"port\")[] = [];\n\tfor (const item of value) {\n\t\tif (item !== \"log\" && item !== \"port\") throw new Error(`Unknown readiness condition: ${String(item)}`);\n\t\tresult.push(item);\n\t}\n\treturn result;\n}\n\nfunction readySpec(value: unknown): DaemonReadySpec {\n\tconst source = record(value, \"ready\");\n\tconst log = optionalString(source.log, \"ready.log\");\n\tconst port = optionalNumber(source.port, \"ready.port\");\n\tconst host = optionalString(source.host, \"ready.host\");\n\tconst timeoutMs = numberValue(source.timeoutMs, \"ready.timeoutMs\");\n\tif (!log && port === undefined) throw new Error(\"ready requires log or port\");\n\treturn { log, port, host, timeoutMs };\n}\n\n/** Decode and validate a daemon launch specification. */\nexport function parseDaemonSpec(value: unknown): DaemonSpec {\n\tconst source = record(value, \"daemon spec\");","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/launch/protocol.ts#L211-L247","documentation":"Thrown by readyPendingList() when an element of the readyPending array is neither 'log' nor 'port'. Each entry must be a recognized readiness condition type; anything else is rejected.","triggerScenarios":"parseDaemonSnapshot receiving readyPending entries like \"http\", \"tcp\", \"Log\" (capitalized), or non-string values (numbers, objects) inside the array.","commonSituations":"Newer daemon adding a readiness kind the client doesn't know; custom conditions invented by wrapper tooling; case inconsistencies from code that uppercases enum strings.","solutions":["Restrict entries to exactly \"log\" or \"port\"","Upgrade client and daemon together if a new readiness kind was introduced","Normalize case and remove unknown entries at the producer before sending"],"exampleFix":"// before\nsnapshot = { id: \"d1\", state: \"starting\", readyPending: [\"http\"] }\n// after\nsnapshot = { id: \"d1\", state: \"starting\", readyPending: [\"port\"] }","handlingStrategy":"validation","validationCode":"function isReadyPending(v: unknown): v is (\"log\" | \"port\")[] {\n  return Array.isArray(v) && v.every((x) => x === \"log\" || x === \"port\");\n}\n// filter unknown entries defensively before parsing:\nsnapshot.readyPending = (snapshot.readyPending ?? []).filter((x) => x === \"log\" || x === \"port\");","typeGuard":"function isReadinessCondition(v: unknown): v is \"log\"|\"port\" { return v === \"log\" || v === \"port\"; }","tryCatchPattern":"try {\n  const snap = parseDaemonSnapshot(raw);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith(\"Unknown readiness condition\")) {\n    // newer daemon introduced a condition type: upgrade client or drop unknown entries\n  } else throw err;\n}","preventionTips":["Only emit \"log\" or \"port\" as readiness conditions","Coordinate client/daemon upgrades when adding new readiness kinds","Lowercase and normalize condition names before serialization","Union-type the condition list and let the compiler reject invalid entries"],"tags":["validation","enum","arrays","ipc"],"backgroundTag":"invalid-enum-value","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}