can1357/oh-my-pi · error · Error

AI staging request failed: ${response.errorMessage ?? "unkno

Error message

AI staging request failed: ${response.errorMessage ?? "unknown error"}

What it means

The completer sends the user prompt plus file diffs to the selected model and checks the response's stopReason. A stopReason of "error" means the provider request failed; the raw errorMessage (or "unknown error") is wrapped in this error. This surfaces upstream API failures (rate limits, invalid key, server errors, aborts) to the AI-stage caller.

Source

Thrown at packages/coding-agent/src/cli/git-tui/ai-stage.ts:235

/** One text completion against the resolved model. */
function createCompleter(
	model: Model<Api>,
	apiKey: ApiKey,
	signal?: AbortSignal,
): (userPrompt: string) => Promise<string> {
	return async userPrompt => {
		const response = await retryTransientCompletion(
			() =>
				completeSimple(
					model,
					{ messages: [{ role: "user", content: userPrompt, timestamp: Date.now() }] },
					{ apiKey, maxTokens: SAFE_MAX_TOKENS, temperature: 0, disableReasoning: true, signal },
				),
			{ signal },
		);
		if (response.stopReason === "error") {
			throw new Error(`AI staging request failed: ${response.errorMessage ?? "unknown error"}`);
		}
		return extractText(response.content);
	};
}

/**
 * Fan out one judgement per item. A failed judgement rejects just its item so
 * one flaky request cannot sink the run — unless every item failed, which
 * means the backend is broken and the first error surfaces.
 */
async function judgeAll<T>(items: readonly T[], run: (item: T) => Promise<boolean>): Promise<boolean[]> {
	let failures = 0;
	let firstError: unknown;
	const verdicts = await Promise.all(
		items.map(async item => {
			try {
				return await run(item);
			} catch (error) {

View on GitHub (pinned to 9690622007)

Solutions

  1. Read the wrapped errorMessage to identify the cause (401 → fix key, 429 → retry later).
  2. Retry the staging command; transient rate limits and outages resolve on their own.
  3. Re-authenticate or update the provider API key.
  4. Reduce diff size (stage fewer files at once) if the request is being rejected for size/token limits.

Example fix

// before
await aiStage(opts); // surfaces raw provider error
// after
try { await aiStage(opts); }
catch (e) {
  if (String(e.message).includes("429")) await Bun.sleep(5000), retry();
  else throw e;
}
Defensive patterns

Strategy: retry

Validate before calling

// preflight reachability/auth
const res = await fetch(`${providerBaseUrl}/models`, { headers: { Authorization: `Bearer ${apiKey}` } });
if (!res.ok) throw new Error(`Provider preflight failed: ${res.status}`);

Try / catch

try {
  await aiStage(opts);
} catch (e) {
  const msg = e instanceof Error ? e.message : "";
  if (msg.includes("AI staging request failed") && (msg.includes("429") || msg.includes("503"))) {
    await Bun.sleep(5000);
    return aiStage(opts); // one retry for transient errors
  }
  throw e;
}

Prevention

When it happens

Trigger: The LLM stream completes with response.stopReason === "error" — e.g. HTTP 401 (invalid key), 429 (rate limit), 5xx provider outage, network failure mid-request, or a signal abort reported as an error.

Common situations: Expired or revoked API key, exceeding provider rate limits with large diffs, provider outage, or corporate proxy blocking the endpoint.

Related errors


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