{"record":{"id":"9be06f2c5d4de706","repo":"Budibase/budibase","slug":"gemini-ingest-did-not-return-file-id","errorCode":null,"errorMessage":"Gemini ingest did not return file_id","messagePattern":"Gemini ingest did not return file_id","errorType":"http","errorClass":"HTTPError","httpStatus":500,"severity":"error","filePath":"packages/server/src/sdk/workspace/ai/knowledgeBase/geminiFileStore.ts","lineNumber":251,"sourceCode":"    console.error(\"Gemini ingest failed\", { error: payload.error })\n    if (payload.error.includes(\"fileSearchStores\")) {\n      if (payload.error.includes(\"403\")) {\n        throw new HTTPError(\n          \"Gemini file store is inaccessible (403 Forbidden). Use 'Reset store' to recreate it.\",\n          403\n        )\n      }\n      if (payload.error.includes(\"404\")) {\n        throw new HTTPError(\n          \"Gemini file store was not found (404). Use 'Reset store' to recreate it.\",\n          404\n        )\n      }\n    }\n    throw new HTTPError(payload.error, 500)\n  }\n  if (!payload.file_id) {\n    throw new HTTPError(\"Gemini ingest did not return file_id\", 500)\n  }\n  return {\n    fileId: payload.file_id,\n  }\n}\n\nexport async function searchGeminiFileStore({\n  vectorStoreId,\n  query,\n}: {\n  vectorStoreId: string\n  query: string\n}): Promise<RagSearchResultItem[]> {\n  const geminiApiKey = getGeminiApiKey()\n  const sessionId = getLiteLLMSessionId()\n  const response = await requestWithRetries(async () =>\n    fetch(\n      `${environment.LITELLM_URL}/v1/vector_stores/${encodeURIComponent(","sourceCodeStart":233,"sourceCodeEnd":269,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/ai/knowledgeBase/geminiFileStore.ts#L233-L269","documentation":"ingestGeminiFile treats a missing file_id in a non-failed ingest payload as a contract violation: without file_id the file cannot be tracked or removed later, so HTTPError 500 is thrown. Like error 514, this signals an unexpected response shape from LiteLLM.","triggerScenarios":"LiteLLM returns a 2xx ingest response whose JSON lacks file_id (different envelope, partial success response, or a proxy returning a non-ingest body).","commonSituations":"LiteLLM version not implementing the /v1/rag/ingest contract fully; proxy/gateway intercepting and returning 2xx with empty body; LiteLLM upgrade changed response field naming.","solutions":["Log/inspect the raw ingest response body to see what LiteLLM actually returned","Upgrade or fix the LiteLLM proxy so /v1/rag/ingest returns { file_id, status, vector_store_id }","Retry ingest; if it persists, reset the store and re-upload"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":"const hasFileId = (p: unknown): p is { file_id: string } =>\n  typeof p === \"object\" && p !== null && typeof (p as { file_id?: unknown }).file_id === \"string\"\n","tryCatchPattern":"try {\n  const { fileId } = await ingestGeminiFile({ ... })\n} catch (e) {\n  if (e instanceof HTTPError && e.message.includes(\"did not return file_id\")) {\n    // inspect LiteLLM response; upgrade proxy or retry ingest\n  }\n}","preventionTips":["Pin a LiteLLM version that returns file_id from /v1/rag/ingest","Integration-test the ingest endpoint against your proxy","Alert on 2xx responses missing required fields"],"tags":["api-contract","litellm","gemini","ingest"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}