can1357/oh-my-pi · error
Unknown restart policy: ${policy}
Error message
Unknown restart policy: ${policy} What it means
Thrown by restartPolicy() when a daemon spec's restart policy string is not one of 'no', 'on-failure', or 'always'. The policy drives the daemon supervisor, so an unrecognized value is rejected at parse time rather than silently defaulting.
Source
Thrown at packages/coding-agent/src/launch/protocol.ts:215
function stringRecord(value: unknown, label: string): Record<string, string> {
const source = record(value, label);
const result: Record<string, string> = {};
for (const key in source) result[key] = rawString(source[key], `${label}.${key}`);
return result;
}
function daemonState(value: unknown): DaemonState {
const state = stringValue(value, "daemon state");
if (state === "starting" || state === "running" || state === "ready" || state === "restarting") return state;
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;
}View on GitHub (pinned to 9690622007)
Solutions
- Use exactly one of: "no", "on-failure", "always"
- Quote the value in YAML configs so "no" is not coerced to boolean false
- Normalize case/underscores to the kebab-case enum at the producer
Example fix
// before
parseDaemonSpec({ id: "d1", command: ["srv"], restartPolicy: "unless-stopped" })
// after
parseDaemonSpec({ id: "d1", command: ["srv"], restartPolicy: "always" }) Defensive patterns
Strategy: validation
Validate before calling
const POLICIES = ["no", "on-failure", "always"] as const;
type RestartPolicyCheck = typeof POLICIES[number];
function isValidPolicy(v: unknown): v is RestartPolicyCheck {
return typeof v === "string" && (POLICIES as readonly string[]).includes(v);
}
if (!isValidPolicy(spec.restartPolicy)) throw new Error(`bad restartPolicy: ${spec.restartPolicy}`); Type guard
function isValidPolicy(v: unknown): v is "no"|"on-failure"|"always" { return typeof v === "string" && ["no","on-failure","always"].includes(v); } Try / catch
try {
const spec = parseDaemonSpec(raw);
} catch (err) {
if (err instanceof Error && err.message.startsWith("Unknown restart policy")) {
// map Docker-style policies (unless-stopped → always) and retry
} else throw err;
} Prevention
- Quote 'no' in YAML configs so it is not parsed as boolean false
- Only use the three documented values; translate external policy vocab at the edge
- Centralize the policy union type and import it in both config loading and sending code
- Validate configs at load time with the union type rather than at daemon parse time
When it happens
Trigger: parseDaemonSpec receiving restartPolicy values like "unless-stopped" (Docker-style), "never", "ALWAYS" (case mismatch), "on_failure" (underscore), or null/undefined in the spec.
Common situations: Copying restart-policy vocabulary from Docker/systemd into daemon config; YAML unquoted 'no' being parsed as boolean false in some formats then stringified differently; typos like 'onfailure'.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Unknown daemon state: ${state}
- Unknown daemon signal: ${signal}
- Unknown readiness condition: ${String(item)}
- ready requires log or port
- Unsupported language '{value}'. Supported: {}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/566d94ba2d46cc07.
Report an issue: GitHub.