{"record":{"id":"0ff9e5caa9fbf3cc","repo":"can1357/oh-my-pi","slug":"gemini-developer-api-error-response-status","errorCode":null,"errorMessage":"Gemini Developer API error (${response.status}): ${errorText}","messagePattern":"Gemini Developer API error \\((.+?)\\): (.+?)","errorType":"exception","errorClass":"SearchProviderError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/web/search/providers/gemini.ts","lineNumber":597,"sourceCode":"\t\t\t\t? { \"cf-aig-authorization\": `Bearer ${apiKey}` }\n\t\t\t\t: { \"x-goog-api-key\": apiKey }),\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\tAccept: \"text/event-stream\",\n\t\t},\n\t\tbody: JSON.stringify(requestBody),\n\t\tsignal: withHardTimeout(signal, timeoutMs),\n\t\tfetch: fetchImpl,\n\t\tmaxAttempts: MAX_RETRIES + 1,\n\t\tdefaultDelayMs: attempt => BASE_DELAY_MS * 2 ** attempt,\n\t\tmaxDelayMs: RATE_LIMIT_BUDGET_MS,\n\t});\n\n\tif (!response.ok) {\n\t\tconst rawErrorText = await response.text();\n\t\tconst errorText = apiKey ? rawErrorText.split(apiKey).join(\"[redacted]\") : rawErrorText;\n\t\tconst classified = classifyProviderHttpError(\"gemini\", response.status, errorText);\n\t\tif (classified) throw classified;\n\t\tthrow new SearchProviderError(\n\t\t\t\"gemini\",\n\t\t\t`Gemini Developer API error (${response.status}): ${errorText}`,\n\t\t\tresponse.status,\n\t\t);\n\t}\n\n\tif (!response.body) {\n\t\tthrow new SearchProviderError(\"gemini\", \"Gemini API returned no response body\", 500);\n\t}\n\n\treturn finalizeGeminiSearchResult(await parseGeminiSearchStream(response.body, model), fetchImpl, signal);\n}\n\n/**\n * Executes a web search using Google Gemini with Google Search grounding.\n */\nexport async function searchGemini(params: GeminiSearchParams): Promise<SearchResponse> {\n\tconst selectedModel = resolveGeminiSearchModel(params.geminiModel);","sourceCodeStart":579,"sourceCodeEnd":615,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/web/search/providers/gemini.ts#L579-L615","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: key from Vertex AI service account JSON used against developer endpoint\nconst apiKey = process.env.VERTEX_KEY;\n// after: dedicated AI Studio developer API key\nconst apiKey = process.env.GEMINI_API_KEY; // https://aistudio.google.com/apikey","handlingStrategy":"try-catch","validationCode":"if (!process.env.GEMINI_API_KEY) throw new Error('Set GEMINI_API_KEY before using the Gemini search provider');","typeGuard":"import { SearchProviderError } from './search-provider-error';\nfunction isSearchProviderError(e: unknown): e is SearchProviderError {\n  return e instanceof SearchProviderError && e.provider === 'gemini';\n}","tryCatchPattern":"try {\n  const result = await searchGemini(params);\n} catch (err) {\n  if (err instanceof SearchProviderError && err.provider === 'gemini') {\n    logger.error('Gemini search failed', { status: err.statusCode, message: err.message });\n    if (err.statusCode && err.statusCode >= 500) return retryWithBackoff();\n    return null; // 4xx: do not retry\n  }\n  throw err;\n}","preventionTips":["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."],"tags":["network","http","api-key","gemini","search-provider"],"backgroundTag":"gemini-api-http-error","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}