{"record":{"id":"ed2c82377f772dcc","repo":"Budibase/budibase","slug":"text-fallbackmessage","errorCode":null,"errorMessage":"${text || fallbackMessage}","messagePattern":"\\$\\{text \\|\\| fallbackMessage\\}","errorType":"http","errorClass":"HTTPError","httpStatus":null,"severity":"error","filePath":"packages/server/src/sdk/workspace/ai/knowledgeBase/geminiFileStore.ts","lineNumber":132,"sourceCode":"    attempt++\n  }\n}\n\nconst handleNotOkResponse = async ({\n  response,\n  fallbackMessage,\n  allowedStatuses = [],\n}: {\n  response: { ok: boolean; status: number; text: () => Promise<string> }\n  fallbackMessage: string\n  allowedStatuses?: number[]\n}): Promise<void> => {\n  if (response.ok || allowedStatuses.includes(response.status)) {\n    return\n  }\n\n  const text = await response.text()\n  throw new HTTPError(text || fallbackMessage, response.status)\n}\n\nconst getCommonAuthHeaders = async () => {\n  const { secretKey } = await getKeySettings()\n  const authKey = environment.LITELLM_MASTER_KEY || secretKey\n  return {\n    \"Content-Type\": \"application/json\",\n    Authorization: `Bearer ${authKey}`,\n  }\n}\n\nexport async function createGeminiFileStore(name: string): Promise<string> {\n  const geminiApiKey = getGeminiApiKey()\n  const response = await fetch(`${environment.LITELLM_URL}/v1/vector_stores`, {\n    method: \"POST\",\n    headers: await getCommonAuthHeaders(),\n    body: JSON.stringify({\n      name,","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/ai/knowledgeBase/geminiFileStore.ts#L114-L150","documentation":"handleNotOkResponse is the shared response checker for all Gemini File Search HTTP calls. When the LiteLLM proxy responds with a non-ok status not in allowedStatuses, it throws HTTPError carrying the raw response body text (or the caller's fallbackMessage) and the upstream status code. It is used by createGeminiFileStore, deleteGeminiVectorStore, ingestGeminiFile, searchGeminiFileStore and deleteGeminiFileFromStore.","triggerScenarios":"Any LiteLLM/Gemini request returns an error status (e.g. 401 bad LiteLLM auth key, 403/404 store access issues, 429 rate limit after retries, 5xx) — the thrown message is the upstream response body.","commonSituations":"LITELLM_MASTER_KEY or key settings secretKey mismatched with the LiteLLM proxy; LITELLM_URL pointing at a wrong/unreachable proxy returning an HTML error page; Gemini upstream rejecting the API key or quota exhausted; vector store deleted upstream while Budibase still references it.","solutions":["Read the thrown message — it is the upstream response body — to identify the real cause","Verify LITELLM_URL and LITELLM_MASTER_KEY / LiteLLM key settings are correct and the proxy is healthy","Check the Gemini API key validity and quota; retry 429/5xx (the code already retries these for some calls)","If the store was deleted upstream, use 'Reset store' to recreate the vector store"],"exampleFix":"// before\nconst res = await fetch(`${LITELLM_URL}/v1/vector_stores`, { headers }) // 401 body thrown raw\n// after\ntry {\n  await createGeminiFileStore(name)\n} catch (e) {\n  if (e instanceof HTTPError && e.status === 401) {\n    // fix LITELLM_MASTER_KEY / key settings\n  }\n}","handlingStrategy":"try-catch","validationCode":"const health = await fetch(`${process.env.LITELLM_URL}/health`)\nif (!health.ok) throw new Error(\"LiteLLM proxy unavailable\")","typeGuard":null,"tryCatchPattern":"try {\n  await createGeminiFileStore(name)\n} catch (e) {\n  if (e instanceof HTTPError) {\n    console.error(`Gemini call failed ${e.status}: ${e.message}`) // body is upstream text\n    // handle 401 (auth key), 429/5xx (retry), 403/404 (reset store)\n  }\n}","preventionTips":["Keep LITELLM_URL and LITELLM_MASTER_KEY / key settings in sync with the proxy","Check LiteLLM proxy health before batch operations","Log response bodies to diagnose upstream failures quickly"],"tags":["http","proxy","litellm","gemini"],"backgroundTag":"upstream-http-error","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}