can1357/oh-my-pi · error
${label} must be a non-empty string
Error message
${label} must be a non-empty string What it means
stringValue(value, label) validates that a required wire field is a non-empty string. It backs optionalString, state, policy, signal, parseDaemonSpec, and parseDaemonSnapshot — so any required string field (ids, names, state values, signals) that is missing, empty, or not a string triggers '<label> must be a non-empty string'.
Source
Thrown at packages/coding-agent/src/launch/protocol.ts:158
event: "daemon-completed";
completionId: string;
owner: string;
daemon: DaemonSnapshot;
}
export type DaemonWireMessage = DaemonWireResponse | DaemonCompletionNotification;
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null && !Array.isArray(value);
}
function record(value: unknown, label: string): Record<string, unknown> {
if (!isRecord(value)) throw new Error(`${label} must be an object`);
return value;
}
function stringValue(value: unknown, label: string): string {
if (typeof value !== "string" || value.length === 0) throw new Error(`${label} must be a non-empty string`);
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 {View on GitHub (pinned to 9690622007)
Solutions
- Populate the field named in the error label with a non-empty string before sending
- Validate payloads client-side with the same protocol validators before writing to the socket
- Sync to matching client/broker versions and update any field renames
Example fix
// before
socket.write(JSON.stringify({ op: "start" })); // missing name
// after
socket.write(JSON.stringify({ op: "start", name: "dev-agent" })); Defensive patterns
Strategy: validation
Validate before calling
const required = ['id', 'name', 'state'];
for (const key of required) {
if (typeof payload[key] !== 'string' || payload[key].length === 0) throw new Error(`${key} must be a non-empty string`);
} Type guard
function isNonEmptyString(v: unknown): v is string {
return typeof v === 'string' && v.length > 0;
} Try / catch
try {
const spec = parseDaemonSpec(raw);
} catch (err) {
if (err.message.includes('must be a non-empty string')) {
logger.warn('daemon payload rejected: missing required string field', { detail: err.message });
return;
}
throw err;
} Prevention
- Fill all required string fields before sending RPCs; never send empty strings as placeholders
- Validate client-side with the same parse/validate helpers the protocol uses
- Update client code when protocol fields become required or are renamed
When it happens
Trigger: Omitting a required field in a daemon RPC (e.g. missing id/name); sending "" for a required string; sending a number/boolean where a string is expected in a spec or snapshot payload.
Common situations: Hand-built RPC payloads missing required fields; clients built against an older protocol version whose fields were renamed or made required; templates with unfilled values serialized as empty strings.
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
- Pending daemon completion is not an event
- ${label} must be an object
- Provider file content hash must be a lowercase or uppercase
- Gemini Files API finalize response contains an invalid file.
- send requires data or signal
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/5c1b5c52ca85f21f.
Report an issue: GitHub.