{"record":{"id":"4b8ca71b629a1c49","repo":"decolua/9router","slug":"antigravity-api-error-response-status","errorCode":null,"errorMessage":"Antigravity API error: ${response.status}","messagePattern":"Antigravity API error: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"open-sse/services/usage/google.js","lineNumber":154,"sourceCode":"      }),\n    }, 10000, proxyOptions);\n\n    if (response.status === 403) {\n      return {\n        message: \"Antigravity quota API access forbidden. Chat may still work.\",\n        quotas: {}\n      };\n    }\n\n    if (response.status === 401) {\n      return {\n        message: \"Antigravity quota API authentication expired. Chat may still work.\",\n        quotas: {}\n      };\n    }\n\n    if (!response.ok) {\n      throw new Error(`Antigravity API error: ${response.status}`);\n    }\n\n    const data = await response.json();\n    const quotas = {};\n\n    // Parse model quotas (inspired by vscode-antigravity-cockpit)\n    if (data.models) {\n      // Filter only recommended/important models (must match PROVIDER_MODELS ag ids)\n      const importantModels = [\n        'gemini-3.7-flash-high',\n        'gemini-3.7-flash-medium',\n        'gemini-3.7-flash-low',\n        'gemini-3.6-flash-high',\n        'gemini-3.6-flash-medium',\n        'gemini-3.6-flash-low',\n        'gemini-3.5-flash-low',\n        'gemini-3.5-flash-extra-low',\n        'gemini-pro-agent',","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/open-sse/services/usage/google.js#L136-L172","documentation":"getAntigravityUsage calls the Antigravity quota API and throws this error when the response status is not OK and not the handled 401-auth-expired case. Unlike 401 (which returns a graceful 'authentication expired' object), any other non-2xx status (403, 429, 5xx) surfaces as a raw status code with no body detail.","triggerScenarios":"The Antigravity quota endpoint returns 403 (forbidden credential/scope), 429 (rate limited), or 5xx (upstream outage) while getAntigravityUsage is called from USAGE_HANDLERS or the usage route.","commonSituations":"Refresh token flow produced a valid-but-underprivileged credential; too-frequent quota polling; Google-side outage; region/blocking returning 403.","solutions":["Check response.status via the message: 429 → back off and retry later; 403 → re-auth with correct scopes; 5xx → retry after delay","Re-run the Antigravity OAuth flow to refresh credentials if 403 persists","Reduce polling frequency of the usage endpoint to avoid rate limiting","Confirm the Antigravity service is not in an outage window"],"exampleFix":"// before\nif (!response.ok) {\n  throw new Error(`Antigravity API error: ${response.status}`);\n}\n// after\nif (!response.ok) {\n  const body = await response.text().catch(() => \"\");\n  throw new Error(`Antigravity API error: ${response.status} ${body.slice(0, 200)}`);\n}","handlingStrategy":"retry","validationCode":"// Ensure credentials are fresh before polling quotas\nif (!account?.antigravity?.accessToken) return { authExpired: true };","typeGuard":null,"tryCatchPattern":"try {\n  usage = await getAntigravityUsage(account);\n} catch (e) {\n  const status = Number(/Antigravity API error: (\\d+)/.exec(e.message)?.[1]);\n  if (status === 429) { await sleep(60_000); return retry(); }\n  if (status === 403) return { reconnect: true };\n  throw e;\n}","preventionTips":["Back off on 429; do not hammer the quota endpoint","Re-auth on persistent 403","Treat 5xx as transient and retry with jitter","Reduce polling frequency in dashboards"],"tags":["http","antigravity","google","quota"],"backgroundTag":"upstream-api-http-error","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}