can1357/oh-my-pi · error
${label} must be a boolean
Error message
${label} must be a boolean What it means
Thrown by booleanValue(), the strict boolean validator for daemon protocol payloads. Any field parsed as a boolean (e.g. 'detached' in a spec, operation flags, snapshot fields) that arrives as anything other than true/false raises this. It guards against truthy/falsy values leaking across the daemon IPC boundary.
Source
Thrown at packages/coding-agent/src/launch/protocol.ts:177
return value;
}
function rawString(value: unknown, label: string): string {
if (typeof value !== "string") throw new Error(`${label} must be a string`);
return value;
}
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;View on GitHub (pinned to 9690622007)
Solutions
- Read the label in the message to identify the offending field
- Change the producer to emit a real JSON boolean (true/false)
- Convert numeric/string flags at the producer boundary (Boolean(value) or value === "true")
- If the field should be omittable, wrap with a default at the producer instead of sending undefined
Example fix
// before
parseDaemonSpec({ id: "d1", command: ["sleep", "1"], detached: 1 })
// after
parseDaemonSpec({ id: "d1", command: ["sleep", "1"], detached: true }) Defensive patterns
Strategy: validation
Validate before calling
function assertBooleanFields(obj: Record<string, unknown>, fields: string[]): void {
for (const f of fields) {
if (typeof obj[f] !== "boolean") throw new Error(`field '${f}' must be a boolean`);
}
}
// normalize first: obj.detached = obj.detached === 1 || obj.detached === "true"; Type guard
function isBoolean(v: unknown): v is boolean { return typeof v === "boolean"; } Try / catch
try {
const spec = parseDaemonSpec(payload);
} catch (err) {
if (err instanceof Error && err.message.includes("must be a boolean")) {
// coerce 0/1 and "true"/"false" strings at the producer and retry once
} else throw err;
} Prevention
- Use real JSON booleans in configs (quote YAML "no"/"yes" values to avoid coercion)
- Run payloads through a schema validator (zod/arktype) before parseDaemon*
- Avoid passing CLI/query-string values directly — convert to booleans at the boundary
- Type the payload with the exported DaemonSpec type before sending
When it happens
Trigger: Passing a payload to parseDaemonSpec, parseDaemonWireRequest, parseDaemonOperation, parseDaemonSnapshot, or parseDaemonRpcResult where a boolean field is 0/1, "true" (string), null, or missing (undefined) instead of an actual boolean.
Common situations: Config files using yes/no or 0/1 for booleans; query-string or CLI parsing that yields strings; a producer serializing 'detached: null' after failed initialization; schema drift between daemon versions.
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 a finite number
- ${label} must be an array of strings
- Invalid boolean value: ${rawValue}. Use true/false, yes/no,
- vault:// path resolution only supports plain filesystem path
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/90327c0e85062cf8.
Report an issue: GitHub.