can1357/oh-my-pi · error

type must be a string or non-empty array of strings

Error message

type must be a string or non-empty array of strings

What it means

The yield tool's optional `type` parameter classifies the result (string or non-empty array of strings). parseYieldType accepts undefined/null (treated as untyped) and valid shapes, and throws a plain Error for anything else — e.g. numbers, empty arrays, or arrays containing non-strings. Note strict-mode providers can deliver `type: null`, which is deliberately tolerated.

Source

Thrown at packages/coding-agent/src/tools/yield.ts:103

			items: { type: "string" },
		},
	],
	description: "Optional result type. A non-empty string array is incremental; a string is terminal.",
};

function isYieldType(value: unknown): value is string | string[] {
	return (
		typeof value === "string" ||
		(Array.isArray(value) && value.length > 0 && value.every(item => typeof item === "string"))
	);
}

function parseYieldType(value: unknown): string | string[] | undefined {
	// Strict-mode providers (OpenAI/Codex) make the optional `type` property
	// required+nullable, so an untyped final yield arrives as `type: null`.
	if (value === undefined || value === null) return undefined;
	if (isYieldType(value)) return value;
	throw new Error("type must be a string or non-empty array of strings");
}
/** Parse a `{`/`[`-leading JSON string; undefined on non-container or parse failure. */
function parseJsonContainerString(value: string): unknown {
	const trimmed = value.trim();
	if (!(trimmed.startsWith("{") || trimmed.startsWith("["))) return undefined;
	try {
		return JSON.parse(trimmed);
	} catch {
		return undefined;
	}
}

function isPlainRecord(value: unknown): value is Record<string, unknown> {
	return typeof value === "object" && value !== null && !Array.isArray(value);
}

/**
 * Resolve the `result` record from raw yield arguments, losslessly salvaging

View on GitHub (pinned to 9690622007)

Solutions

  1. Omit `type` entirely (or send null) when there is no classification.
  2. Send a single string, e.g. "finding".
  3. Send a non-empty array of strings for multiple classifications, e.g. ["security","high"].
  4. Ensure all array elements are strings — convert enums/numbers to strings before passing.

Example fix

// before
yield({ result: { data: x }, type: [] })
// after
yield({ result: { data: x }, type: "finding" })
Defensive patterns

Strategy: type-guard

Validate before calling

const t = (p: { type?: unknown }).type; if (t !== undefined && t !== null && typeof t !== "string" && !(Array.isArray(t) && t.length > 0 && t.every((s) => typeof s === "string"))) throw new Error("type must be a string or non-empty array of strings");

Type guard

function isYieldType(v: unknown): v is string | string[] { return typeof v === "string" || (Array.isArray(v) && v.length > 0 && v.every((s) => typeof s === "string")); }

Try / catch

try { yield(params); } catch (e) { if (e.message === "type must be a string or non-empty array of strings") { delete params.type; return yield(params); } throw e; }

Prevention

When it happens

Trigger: Passing `type: 42`, `type: true`, `type: {}`, `type: []` (empty array), or `type: [1,2]` in the yield tool parameters.

Common situations: A model emits a numeric type code or an empty array when it has no classification; prompt/schema drift causes the model to fill `type` with an invalid literal.

Related errors


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