can1357/oh-my-pi · error · SearchProviderError
Gemini Developer API error
Error message
Gemini Developer API error (${response.status}): ${errorText} What it means
Thrown by callGeminiDeveloperSearch in the Gemini web-search provider when the Gemini Developer API (streamGenerateContent endpoint) returns a non-OK HTTP status. Before throwing, the provider redacts the API key from the response body and attempts to classify the error via classifyProviderHttpError; this generic SearchProviderError is only the fallback for statuses/text that classifier does not recognize. The HTTP status and raw (redacted) error body are embedded in the message so the developer can see Google's actual reason.
Solutions
- Read the HTTP status and errorText embedded in the message; fix the specific cause (enable Generative Language API for the key, correct model id, fix request params).
- Verify GEMINI_API_KEY (or provider 'google' key) is a valid Developer API key at https://aistudio.google.com/apikey and not IP/referrer-restricted.
- If 429/401/403 quota-or-auth style, rely on the classifier's specific error or rotate to a different credential/provider.
- Retry later on 5xx; the request already went through fetchWithRetry with exponential backoff, so persistent 5xx means a Google-side incident or a persistent request problem.
Example fix
// before: key from Vertex AI service account JSON used against developer endpoint const apiKey = process.env.VERTEX_KEY; // after: dedicated AI Studio developer API key const apiKey = process.env.GEMINI_API_KEY; // https://aistudio.google.com/apikey
Defensive patterns
Strategy: try-catch
Validate before calling
if (!process.env.GEMINI_API_KEY) throw new Error('Set GEMINI_API_KEY before using the Gemini search provider'); Type guard
import { SearchProviderError } from './search-provider-error';
function isSearchProviderError(e: unknown): e is SearchProviderError {
return e instanceof SearchProviderError && e.provider === 'gemini';
} Try / catch
try {
const result = await searchGemini(params);
} catch (err) {
if (err instanceof SearchProviderError && err.provider === 'gemini') {
logger.error('Gemini search failed', { status: err.statusCode, message: err.message });
if (err.statusCode && err.statusCode >= 500) return retryWithBackoff();
return null; // 4xx: do not retry
}
throw err;
} Prevention
- Use a dedicated AI Studio (developer API) key, not a Vertex AI credential.
- Enable the Generative Language API for the key's Google Cloud project.
- Avoid referrer/IP restrictions on the key that exclude your runtime host.
- Pin and test the model id you pass to the provider against the developer API roster.
When it happens
Trigger: Any non-2xx response from POST {endpoint}/models/{model}:streamGenerateContent?alt=sse whose status/body is not matched by classifyProviderHttpError — e.g. 400 invalid request body, 403 API key restrictions or disabled API, 404 unknown model id on the developer API endpoint, 5xx outages.
Common situations: Using an API key created for Vertex AI instead of the Developer API; Google Cloud APIs (Generative Language API) not enabled for the key's project; API key restricted by referrer/IP or to other APIs; requesting a model name not available on the developer endpoint; transient Google 5xx incidents.
Related errors
- Gemini Files API delete failed with HTTP
- Gemini Files API upload finalization failed with HTTP
- Jina API error ( )
- Gemini image request failed
- Anthropic API error ( )
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/0ff9e5caa9fbf3cc.
Report an issue: GitHub.
Appendix: source
Thrown at packages/coding-agent/src/web/search/providers/gemini.ts:597
? { "cf-aig-authorization": `Bearer ${apiKey}` }
: { "x-goog-api-key": apiKey }),
"Content-Type": "application/json",
Accept: "text/event-stream",
},
body: JSON.stringify(requestBody),
signal: withHardTimeout(signal, timeoutMs),
fetch: fetchImpl,
maxAttempts: MAX_RETRIES + 1,
defaultDelayMs: attempt => BASE_DELAY_MS * 2 ** attempt,
maxDelayMs: RATE_LIMIT_BUDGET_MS,
});
if (!response.ok) {
const rawErrorText = await response.text();
const errorText = apiKey ? rawErrorText.split(apiKey).join("[redacted]") : rawErrorText;
const classified = classifyProviderHttpError("gemini", response.status, errorText);
if (classified) throw classified;
throw new SearchProviderError(
"gemini",
`Gemini Developer API error (${response.status}): ${errorText}`,
response.status,
);
}
if (!response.body) {
throw new SearchProviderError("gemini", "Gemini API returned no response body", 500);
}
return finalizeGeminiSearchResult(await parseGeminiSearchStream(response.body, model), fetchImpl, signal);
}
/**
* Executes a web search using Google Gemini with Google Search grounding.
*/
export async function searchGemini(params: GeminiSearchParams): Promise<SearchResponse> {
const selectedModel = resolveGeminiSearchModel(params.geminiModel);View on GitHub (pinned to 9690622007)