can1357/oh-my-pi · error
daemon.readyPending must be an array
Error message
daemon.readyPending must be an array
What it means
Thrown by readyPendingList() when the snapshot's readyPending field is not an array. readyPending tracks which readiness conditions ('log'/'port') are still being awaited, and the parser requires it to always be an array, even when empty.
Source
Thrown at packages/coding-agent/src/launch/protocol.ts:226
if (state === "stopping" || state === "exited" || state === "failed") return state;
throw new Error(`Unknown daemon state: ${state}`);
}
function restartPolicy(value: unknown): DaemonRestartPolicy {
const policy = stringValue(value, "restart policy");
if (policy === "no" || policy === "on-failure" || policy === "always") return policy;
throw new Error(`Unknown restart policy: ${policy}`);
}
function daemonSignal(value: unknown): DaemonSignal {
const signal = stringValue(value, "signal");
if (signal === "SIGINT" || signal === "SIGTERM" || signal === "SIGHUP") return signal;
if (signal === "SIGQUIT" || signal === "SIGKILL") return signal;
throw new Error(`Unknown daemon signal: ${signal}`);
}
function readyPendingList(value: unknown): ("log" | "port")[] {
if (!Array.isArray(value)) throw new Error("daemon.readyPending must be an array");
const result: ("log" | "port")[] = [];
for (const item of value) {
if (item !== "log" && item !== "port") throw new Error(`Unknown readiness condition: ${String(item)}`);
result.push(item);
}
return result;
}
function readySpec(value: unknown): DaemonReadySpec {
const source = record(value, "ready");
const log = optionalString(source.log, "ready.log");
const port = optionalNumber(source.port, "ready.port");
const host = optionalString(source.host, "ready.host");
const timeoutMs = numberValue(source.timeoutMs, "ready.timeoutMs");
if (!log && port === undefined) throw new Error("ready requires log or port");
return { log, port, host, timeoutMs };
}
View on GitHub (pinned to 9690622007)
Solutions
- Have the producer always emit an array for readyPending, e.g. [] when nothing is pending
- Wrap single values: "port" → ["port"]
- Align daemon and client versions so the field is always present
Example fix
// before
snapshot = { id: "d1", state: "starting", readyPending: "port" }
// after
snapshot = { id: "d1", state: "starting", readyPending: ["port"] } Defensive patterns
Strategy: validation
Validate before calling
function isReadyPending(v: unknown): v is ("log" | "port")[] {
return Array.isArray(v) && v.every((x) => x === "log" || x === "port");
}
if (!isReadyPending(snapshot.readyPending)) {
snapshot.readyPending = Array.isArray(snapshot.readyPending) ? snapshot.readyPending : [];
} Type guard
function isReadyPending(v: unknown): v is ("log"|"port")[] { return Array.isArray(v) && v.every((x) => x === "log" || x === "port"); } Try / catch
try {
const snap = parseDaemonSnapshot(raw);
} catch (err) {
if (err instanceof Error && err.message === "daemon.readyPending must be an array") {
// treat as legacy snapshot: default readyPending to [] and retry
} else throw err;
} Prevention
- Always emit readyPending as an array from the daemon, even when empty
- Never serialize a single condition string — wrap it in a list
- Keep old daemons from omitting the field: gate the field behind a protocol version
- Schema-validate snapshots before parsing
When it happens
Trigger: parseDaemonSnapshot receiving a payload where readyPending is undefined, null, an object, or a single string like "port" instead of an array.
Common situations: Older daemon versions omitting the field entirely; a producer serializing a single readiness condition without wrapping it in a list; JSON schema drift between client and daemon.
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
- ${label} must be a string
- ${label} must be an array of strings
- Unknown daemon state: ${state}
- Unknown readiness condition: ${String(item)}
- response.ok must be a boolean
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/81554dd3566af691.
Report an issue: GitHub.