{"record":{"id":"9af2b79408e4b9df","repo":"srbhr/Resume-Matcher","slug":"failed-to-load-api-key-status-status-res-status","errorCode":null,"errorMessage":"Failed to load API key status (status ${res.status}).","messagePattern":"Failed to load API key status \\(status (.+?)\\)\\.","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/frontend/lib/api/config.ts","lineNumber":483,"sourceCode":"export const API_KEY_PROVIDER_INFO: Record<ApiKeyProvider, { name: string; description: string }> =\n  {\n    openai: { name: 'OpenAI', description: 'GPT-4, GPT-4o, etc.' },\n    azure_foundry: { name: 'Azure AI Foundry', description: 'Azure AI Inference models' },\n    anthropic: { name: 'Anthropic', description: 'Claude 3.5, Claude 4, etc.' },\n    google: { name: 'Google', description: 'Gemini 1.5, Gemini 2, etc.' },\n    openrouter: { name: 'OpenRouter', description: 'Access multiple providers' },\n    deepseek: { name: 'DeepSeek', description: 'DeepSeek chat models' },\n    groq: { name: 'Groq', description: 'Llama, Mixtral, Gemma on Groq' },\n    openai_compatible: { name: 'OpenAI-Compatible', description: 'Self-hosted / proxy endpoints' },\n    ollama: { name: 'Ollama', description: 'Local Ollama server' },\n  };\n\n// Fetch API key status for all providers\nexport async function fetchApiKeyStatus(): Promise<ApiKeyStatusResponse> {\n  const res = await apiFetch('/config/api-keys', { credentials: 'include' });\n\n  if (!res.ok) {\n    throw new Error(`Failed to load API key status (status ${res.status}).`);\n  }\n\n  return res.json();\n}\n\n// Update API keys for one or more providers\nexport async function updateApiKeys(keys: ApiKeysUpdateRequest): Promise<ApiKeysUpdateResponse> {\n  const res = await apiFetch('/config/api-keys', {\n    method: 'POST',\n    headers: { 'Content-Type': 'application/json' },\n    credentials: 'include',\n    body: JSON.stringify(keys),\n  });\n\n  if (!res.ok) {\n    const data = await res.json().catch(() => ({}));\n    throw new Error(data.detail || `Failed to update API keys (status ${res.status}).`);\n  }","sourceCodeStart":465,"sourceCodeEnd":501,"githubUrl":"https://github.com/srbhr/Resume-Matcher/blob/116f9cc3b00e1ac91734a6c2679bf41ea64a0edc/apps/frontend/lib/api/config.ts#L465-L501","documentation":"fetchApiKeyStatus calls GET /config/api-keys (which reports per-provider key presence/validity, never key material) and throws this Error for any non-ok response. It's the standard config-fetcher pattern: only the status code is preserved. A failure here means the backend refused or failed the API-key status query, not that any key is invalid.","triggerScenarios":"Non-2xx from GET /config/api-keys: 401/403 (expired credentials cookie or CSRF failure), 404 (route missing or NEXT_PUBLIC_API_URL/BACKEND_ORIGIN misconfigured so the proxy returns its own 404), 500 when the backend can't read its encrypted key store / DB, 502 when the backend is down.","commonSituations":"Settings page load while the backend is restarting; session timeout mid-browsing; database migration left the key store table missing; dev frontend started without the backend on :8000.","solutions":["Decode the status: 401/403 → log in again; 404 → verify /api/v1/config/api-keys exists and rewrites target BACKEND_ORIGIN; 5xx → check backend logs and DB/key-store health.","Curl the endpoint with the session cookie to isolate proxy vs backend.","Ensure NEXT_PUBLIC_API_URL/BACKEND_ORIGIN are set consistently in the environment.","In calling loaders (keyStatus etc.), catch and render a 'status unavailable' state so the settings page still works."],"exampleFix":"// before\nconst status = await fetchApiKeyStatus();\n\n// after\nconst status = await fetchApiKeyStatus().catch((e) => {\n  console.warn('API key status unavailable', e);\n  return EMPTY_KEY_STATUS; // all providers unknown\n});","handlingStrategy":"fallback","validationCode":"const sessionOk = document.cookie.includes('session');\nif (!sessionOk) await refreshSession(); // avoid guaranteed 401","typeGuard":"function isApiKeyStatusResponse(x: unknown): x is ApiKeyStatusResponse {\n  return typeof x === 'object' && x !== null && 'providers' in x;\n}","tryCatchPattern":"try {\n  status = await fetchApiKeyStatus();\n} catch {\n  status = null; // render 'unknown' state per provider\n  setKeyStatusUnavailable(true);\n}","preventionTips":["Refresh session before long-lived settings pages fetch key status","Health-check the backend before key management UI loads","Treat unknown status as 'not configured', not as an error state","Watch proxy logs for 404/502 on /api/v1/config/api-keys"],"tags":["network","http","api-keys","frontend-api-client"],"backgroundTag":"http-non-2xx-response","analyzedSha":"116f9cc3b00e1ac91734a6c2679bf41ea64a0edc","analyzedAt":"2026-08-28T22:51:40.999Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}