can1357/oh-my-pi · error · ToolError

${response.errorMessage ?? "completion() request failed."}

Error message

${response.errorMessage ?? "completion() request failed."}

What it means

The bridge performs a oneshot completion via `instrumentedCompleteSimple`. When the response's `stopReason` is "error", this ToolError surfaces the provider-reported `errorMessage` (or a generic fallback) to the eval cell. It wraps any upstream LLM request failure — auth rejection, rate limit, malformed request, provider outage, context overflow.

Source

Thrown at packages/coding-agent/src/eval/completion-bridge.ts:174

		instrumentedCompleteSimple(
			model,
			{
				systemPrompt,
				messages: [{ role: "user", content: [{ type: "text", text: prompt }], timestamp: Date.now() }],
				tools,
			},
			{
				apiKey: registry.resolver(model, options.session.getSessionId?.() ?? undefined),
				signal: options.signal,
				reasoning: reasoningForTier(finalTier, model),
				toolChoice: schema ? { type: "tool", name: STRUCTURED_TOOL_NAME } : undefined,
			},
			{ telemetry, oneshotKind: "eval_completion" },
		),
	);

	if (response.stopReason === "error") {
		throw new ToolError(response.errorMessage ?? "completion() request failed.");
	}
	if (response.stopReason === "aborted") {
		throw new ToolError("completion() request aborted.");
	}

	let resultText: string;
	if (schema) {
		const call = extractToolCall(response, STRUCTURED_TOOL_NAME);
		let value: unknown;
		if (call) {
			value = call.arguments;
		} else {
			const text = extractTextContent(response);
			if (!text) throw new ToolError("completion() returned no structured response.");
			try {
				value = parseJsonPayload(text);
			} catch {
				throw new ToolError("completion() did not return a structured response matching the schema.");

View on GitHub (pinned to 9690622007)

Solutions

  1. Read the surfaced provider message in the error text — it names the root cause (auth, quota, context length) and fix accordingly.
  2. For 401/403: refresh or correct the provider credentials.
  3. For 429: add retry/backoff or reduce concurrent eval cells.
  4. For context-length errors: shorten the prompt or target a larger-context model/tier.
  5. Retry the call if the message indicates a transient provider outage (5xx).
Defensive patterns

Strategy: try-catch

Try / catch

let out;
try {
  out = await completion(prompt);
} catch (e) {
  const msg = String(e);
  if (/429|rate limit/i.test(msg)) await Bun.sleep(2000), retry();
  else if (/401|unauthorized/i.test(msg)) fixCredentials();
  else throw e;
}

Prevention

When it happens

Trigger: `completion(prompt, ...)` sends a request and the provider responds with an error stop reason; `response.errorMessage` from the provider layer is non-null and is used verbatim as the thrown message.

Common situations: Expired/revoked API key (401); rate limiting (429) during parallel eval cells; prompt exceeding the model's context window; unsupported parameter combination (e.g. reasoning effort on a non-reasoning model — though the bridge clamps this); transient provider 5xx during a CI run.

Related errors


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