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

  1. Populate the field named in the error label with a non-empty string before sending
  2. Validate payloads client-side with the same protocol validators before writing to the socket
  3. 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

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


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/5c1b5c52ca85f21f. Report an issue: GitHub.