{"record":{"id":"ec918d974d6d4f6b","repo":"can1357/oh-my-pi","slug":"gemini-files-api-upload-initialization-failed-with","errorCode":null,"errorMessage":"Gemini Files API upload initialization failed with HTTP ${startResponse.status}","messagePattern":"Gemini Files API upload initialization failed with HTTP (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/blob-broker/provider-files-gemini.ts","lineNumber":112,"sourceCode":"\t\t\ttry {\n\t\t\t\tstartResponse = await fetchImpl(GEMINI_FILES_UPLOAD_URL, {\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\t\"X-Goog-Upload-Command\": \"start\",\n\t\t\t\t\t\t\"X-Goog-Upload-Header-Content-Length\": String(byteLength),\n\t\t\t\t\t\t\"X-Goog-Upload-Header-Content-Type\": request.mimeType,\n\t\t\t\t\t\t\"X-Goog-Upload-Protocol\": \"resumable\",\n\t\t\t\t\t\t\"x-goog-api-key\": credential,\n\t\t\t\t\t},\n\t\t\t\t\tbody: JSON.stringify(request.filename ? { file: { display_name: request.filename } } : { file: {} }),\n\t\t\t\t\tsignal: request.signal,\n\t\t\t\t});\n\t\t\t} catch {\n\t\t\t\tthrow new Error(\"Gemini Files API upload initialization request failed\");\n\t\t\t}\n\t\t\tif (!startResponse.ok) {\n\t\t\t\tthrow new Error(`Gemini Files API upload initialization failed with HTTP ${startResponse.status}`);\n\t\t\t}\n\n\t\t\tconst uploadUrl = startResponse.headers.get(\"X-Goog-Upload-URL\")?.trim();\n\t\t\tif (!uploadUrl)\n\t\t\t\tthrow new Error(\"Gemini Files API upload initialization response is missing X-Goog-Upload-URL\");\n\n\t\t\tlet finalizeResponse: Response;\n\t\t\ttry {\n\t\t\t\tfinalizeResponse = await fetchImpl(uploadUrl, {\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"Content-Length\": String(byteLength),\n\t\t\t\t\t\t\"X-Goog-Upload-Command\": \"upload, finalize\",\n\t\t\t\t\t\t\"X-Goog-Upload-Offset\": \"0\",\n\t\t\t\t\t},\n\t\t\t\t\tbody: request.bytes,\n\t\t\t\t\tsignal: request.signal,\n\t\t\t\t});","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/blob-broker/provider-files-gemini.ts#L94-L130","documentation":"The 'start' resumable-upload POST completed but returned a non-2xx status; the client includes that status code in the message. Google rejected the initialization request itself — the byte payload was never sent, so this is about the metadata/start handshake, not the file content.","triggerScenarios":"fetchImpl POST to /upload/v1beta/files with X-Goog-Upload-Command: start returns e.g. 400 (bad display_name/header content-type), 403 (invalid API key / API not enabled), 429 (quota), or 5xx (Google outage).","commonSituations":"Invalid or revoked Gemini API key (403); Generative Language API not enabled for the key's project; exceeding upload quota or file-size limits (4xx/429); mimeType not matching the actual file; transient 500/503 during Google incidents.","solutions":["Read the HTTP status from the message: 401/403 → fix the API key / enable the Generative Language API; 429 → check quota; 5xx → retry later.","Verify the API key is valid via curl 'https://generativelanguage.googleapis.com/v1beta/files?key=...'.","Confirm the request mimeType header matches the file and is a supported Gemini Files API type.","For 5xx/429, retry with exponential backoff.","Capture the response body with a debug FetchImpl wrapper for Google's detailed error JSON."],"exampleFix":"// before: treating all failures the same\nawait client.upload(request);\n// after: branch on status from the message\nconst m = /HTTP (\\d+)/.exec(String(e.message));\nif (m && (m[1] === \"429\" || m[1].startsWith(\"5\"))) return retryWithBackoff(upload);\nif (m && (m[1] === \"401\" || m[1] === \"403\")) throw new Error(\"Check GEMINI_API_KEY\");","handlingStrategy":"try-catch","validationCode":"// pre-validate the credential against the API before large uploads\nconst probe = await fetch(\"https://generativelanguage.googleapis.com/v1beta/files\", {\n  headers: { \"x-goog-api-key\": key },\n});\nif (probe.status === 401 || probe.status === 403) throw new Error(\"Gemini API key invalid or API not enabled\");","typeGuard":"null","tryCatchPattern":"try {\n  const handle = await client.upload(request);\n} catch (error) {\n  const status = /HTTP (\\d+)/.exec(error instanceof Error ? error.message : \"\")?.[1];\n  if (status === \"401\" || status === \"403\") throw new Error(\"Fix GEMINI_API_KEY / enable Generative Language API\");\n  if (status === \"429\" || status?.startsWith(\"5\")) return retryWithBackoff(upload);\n  throw error;\n}","preventionTips":["Validate the API key with a lightweight GET /v1beta/files call before big uploads","Ensure the Generative Language API is enabled on the key's Google Cloud project","Respect quota limits and back off on 429","Check request.mimeType correctness — mismatched content types get 4xx on start"],"tags":["http","api-response","upload","authentication"],"backgroundTag":"http-error-status","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}