{"record":{"id":"ef70433c9a2acda4","repo":"rohitg00/agentmemory","slug":"gemini-embedding-failed-response-status-er","errorCode":null,"errorMessage":"Gemini embedding failed (${response.status}): ${err}","messagePattern":"Gemini embedding failed \\((.+?)\\): (.+?)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/providers/embedding/gemini.ts","lineNumber":43,"sourceCode":"    const results: Float32Array[] = [];\n\n    for (let i = 0; i < texts.length; i += BATCH_LIMIT) {\n      const chunk = texts.slice(i, i + BATCH_LIMIT);\n      const response = await fetchWithTimeout(`${API_BASE}?key=${this.apiKey}`, {\n        method: \"POST\",\n        headers: { \"Content-Type\": \"application/json\" },\n        body: JSON.stringify({\n          requests: chunk.map((t) => ({\n            model: MODEL,\n            content: { parts: [{ text: t }] },\n            outputDimensionality: this.dimensions,\n          })),\n        }),\n      });\n\n      if (!response.ok) {\n        const err = await response.text();\n        throw new Error(`Gemini embedding failed (${response.status}): ${err}`);\n      }\n\n      const data = (await response.json()) as {\n        embeddings: Array<{ values: number[] }>;\n      };\n\n      for (const emb of data.embeddings) {\n        results.push(l2Normalize(new Float32Array(emb.values)));\n      }\n    }\n\n    return results;\n  }\n}\n\nlet zeroNormWarned = false;\n\nfunction l2Normalize(vec: Float32Array): Float32Array {","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/rohitg00/agentmemory/blob/e04ba88819c365c9acf9d6661ea802143e728bd6/src/providers/embedding/gemini.ts#L25-L61","documentation":"`embedBatch` in the Gemini provider throws when Google's embedding endpoint returns a non-ok HTTP status, including the status code and raw response body in the message. The key was present (constructor passed) but the API call itself failed — auth, quota, model, or request-shape problems.","triggerScenarios":"Any `embed()`/`embedBatch()` call where the Gemini embeddings endpoint responds 400 (malformed request, unsupported model like a non-embedding model name), 401/403 (bad/missing permissions on the key), 429 (quota/rate limit), or 5xx (Google-side outage).","commonSituations":"Key restricted by API restrictions in Google Cloud console (Generative Language API not allowed); free-tier per-minute quota exhausted under batch load; using `models/embedding-001` vs newer `gemini-embedding` naming mismatch; request disabled via API key restrictions or region not enabled.","solutions":["Inspect the response body embedded in the error — Google's message names the exact cause (API key invalid, quota exceeded, model not found).","If 401/403: generate a new key at Google AI Studio and ensure the Generative Language API is enabled/not restricted for it.","If 429: implement backoff-and-retry, lower request rate and batch size, or upgrade from the free tier.","If 400: verify the model name is a valid embedding model and texts are non-empty and within token limits.","If 5xx: retry with exponential backoff; check Google's status dashboard if it persists."],"exampleFix":"// before\nconst vec = await provider.embed(text); // throws on 429 with body\n// after\nfor (let attempt = 0; attempt < 3; attempt++) {\n  try { return await provider.embed(text); }\n  catch (e) {\n    if (!/\\(429\\)|\\(5\\d\\d\\)/.test(e.message) || attempt === 2) throw e;\n    await sleep(2 ** attempt * 500);\n  }\n}","handlingStrategy":"retry","validationCode":"// Preflight the key against a cheap endpoint before embedding batches\nconst res = await fetch(`https://generativelanguage.googleapis.com/v1/models?key=${process.env.GEMINI_API_KEY}`);\nif (!res.ok) throw new Error(`GEMINI_API_KEY preflight failed: ${res.status}`);","typeGuard":null,"tryCatchPattern":"async function embedWithRetry(text: string, tries = 3) {\n  for (let i = 0; i < tries; i++) {\n    try { return await provider.embed(text); }\n    catch (e) {\n      const m = e instanceof Error ? e.message : String(e);\n      const status = Number(/Gemini embedding failed \\((\\d+)\\)/.exec(m)?.[1]);\n      if (status === 401 || status === 403 || (status >= 400 && status < 500 && status !== 429)) throw e;\n      await new Promise(r => setTimeout(r, 2 ** i * 500 + Math.random() * 250));\n    }\n  }\n  throw new Error(\"Gemini embed: retries exhausted\");\n}","preventionTips":["Restrict the API key correctly in Google Cloud (allow Generative Language API) and verify permissions before deploy.","Throttle batch embedding to stay under Gemini free-tier/paid quota; cache embeddings to reduce calls.","Pin a valid embedding model name and validate it with a single test embed at startup.","Read the response body in the error message — Google states the exact rejection reason."],"tags":["network","http","api-error","embeddings","gemini"],"backgroundTag":"http-api-error","analyzedSha":"e04ba88819c365c9acf9d6661ea802143e728bd6","analyzedAt":"2026-08-30T01:07:40.754Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}