can1357/oh-my-pi · error · AIError.ProviderResponseError

An unknown error occurred

Error message

An unknown error occurred

What it means

streamGoogleGeminiCli finished streaming a response whose output.stopReason was "aborted" or "error", and no provider error message was attached, so this generic fallback text is thrown as AIError.ProviderResponseError. It means the Gemini CLI endpoint signalled a failed/terminated response without explaining why.

Source

Thrown at packages/ai/src/providers/google-gemini-cli.ts:1104

					break;
				} catch (error) {
					const status = extractHttpStatusFromError(error);
					if (
						!isLastEndpoint &&
						!started &&
						(AIError.isTransientStatus(status) ||
							(status === undefined &&
								!(error instanceof AIError.ProviderResponseError && error.kind === "output") &&
								AIError.retriable(AIError.classify(error))))
					) {
						continue;
					}
					throw error;
				}
			}

			if (output.stopReason === "aborted" || output.stopReason === "error") {
				throw new AIError.ProviderResponseError(output.errorMessage ?? "An unknown error occurred", {
					provider: model.provider,
					kind: "output",
				});
			}

			output.duration = performance.now() - startTime;
			if (firstTokenTime) output.ttft = firstTokenTime - startTime;
			stream.push({ type: "done", reason: output.stopReason, message: output });
			stream.end();
		} catch (error) {
			const result = await AIError.finalize(error, { api: model.api, signal: options?.signal, rawRequestDump });
			output.stopReason = result.stopReason;
			output.errorStatus = result.status;
			output.errorId = result.id;
			output.errorMessage = result.message;
			output.duration = performance.now() - startTime;
			if (firstTokenTime) output.ttft = firstTokenTime - startTime;
			stream.push({ type: "error", reason: output.stopReason, error: output });

View on GitHub (pinned to 9690622007)

Solutions

  1. Log the full output object at the callsite to capture stopReason and any partial content before the throw
  2. Check Gemini CLI / Code Assist service status and auth token validity
  3. Retry the request — transient backend failures often produce empty error messages
  4. If aborts are user-driven, check options.signal before treating this as a provider failure

Example fix

// before
throw new AIError.ProviderResponseError(output.errorMessage ?? "An unknown error occurred", { provider: model.provider, kind: "output" });
// after
if (!output.errorMessage) {
  logger.error("gemini-cli opaque error", { stopReason: output.stopReason, provider: model.provider });
}
throw new AIError.ProviderResponseError(output.errorMessage ?? `Gemini CLI stream ended with stopReason=${output.stopReason}`, { provider: model.provider, kind: "output" });
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

null

Try / catch

try {
  await streamGoogleGeminiCli(model, params, { signal });
} catch (err) {
  if (err instanceof AIError.AbortError) throw err; // rethrow user aborts
  if (err instanceof AIError.ProviderResponseError && err.context?.kind === "output") {
    logger.warn("gemini-cli ended without error message", { message: err.message });
    return retryWithBackoff();
  }
  throw err;
}

Prevention

When it happens

Trigger: The aggregated stream output has stopReason "error" or "aborted" but output.errorMessage is null/undefined — e.g. the Gemini CLI backend emitted a terminal chunk with an error stop reason and no message.

Common situations: Gemini Code Assist / CLI backend outages returning opaque error terminations; quota or safety terminations that omit a message; aborted generations surfaced as stop reasons rather than exceptions.

Related errors


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