{"record":{"id":"8a1335ea75e00bb1","repo":"abhigyanpatwari/GitNexus","slug":"llm-api-error-response-status-errortext-sl","errorCode":null,"errorMessage":"LLM API error (${response.status}): ${errorText.slice(0, 500)}","messagePattern":"LLM API error \\((.+?)\\): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"gitnexus/src/core/wiki/llm-client.ts","lineNumber":448,"sourceCode":"  }\n\n  if (!response.ok) {\n    const errorText = await response.text().catch(() => 'unknown error');\n\n    // Azure content filter — surface a clear message instead of a generic API error.\n    if (\n      azure &&\n      response.status === 400 &&\n      (errorText.includes('content_filter') || errorText.includes('ResponsibleAIPolicyViolation'))\n    ) {\n      throw new Error(\n        `Azure content filter blocked this request. The prompt triggered content policy. Details: ${errorText.slice(0, 300)}`,\n      );\n    }\n\n    // Any other non-OK response here is a terminal 4xx — resilientFetch\n    // already retried 5xx/429 to exhaustion and would have thrown above.\n    throw new Error(`LLM API error (${response.status}): ${errorText.slice(0, 500)}`);\n  }\n\n  // Streaming path\n  if (useStream && response.body) {\n    return await readSSEStream(response.body, options!.onChunk!);\n  }\n\n  // Non-streaming path\n  const json = (await response.json()) as any;\n  const choice = json.choices?.[0];\n  if (!choice?.message?.content) {\n    throw new Error('LLM returned empty response');\n  }\n\n  return {\n    content: choice.message.content,\n    promptTokens: json.usage?.prompt_tokens,\n    completionTokens: json.usage?.completion_tokens,","sourceCodeStart":430,"sourceCodeEnd":466,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/52924ef12c2290ceee4612526a828ec4cdf2047f/gitnexus/src/core/wiki/llm-client.ts#L430-L466","documentation":"The endpoint returned a non-OK status that resilientFetch does not retry — a terminal 4xx (5xx/429 were already retried and would have surfaced as the 'after retries' error). The message includes the status code and first 500 chars of the response body. Common statuses: 401/403 (bad key), 404 (wrong base URL path or model), 400 (bad request payload/model name).","triggerScenarios":"Invalid or revoked `--api-key` (401); missing entitlements for the model (403); `--base-url` pointing to a path that is not an OpenAI-compatible chat-completions endpoint (404); unknown `--model` name (400/404); Azure deployment name mismatch.","commonSituations":"Expired API key in ~/.gitnexus/config.json; wrong model identifier after a provider renamed models; base URL missing or adding /v1; Azure deployment vs model-name confusion; corporate proxy returning 403.","solutions":["Read the status + body text: 401/403 → re-authenticate (`gitnexus wiki --api-key ...`), 404 → fix `--base-url` path (usually ends in /v1), 400 → check `--model` spelling","Verify the endpoint manually: curl -H \"Authorization: Bearer $KEY\" $BASE_URL/chat/completions with a minimal payload","For Azure, confirm the deployment name (`--model`) and URL shape https://{resource}.openai.azure.com/openai/v1","Ensure the key has credit/quota and the model is enabled for the account"],"exampleFix":"# before (404 — missing /v1)\ngitnexus wiki --provider custom --base-url https://api.example.com --model gpt-4o-mini\n\n# after\ngitnexus wiki --provider custom --base-url https://api.example.com/v1 --model gpt-4o-mini","handlingStrategy":"try-catch","validationCode":"// Smoke-test credentials and endpoint shape before a long wiki run:\nconst probe = await fetch(`${baseUrl}/chat/completions`, {\n  method: 'POST',\n  headers: { Authorization: `Bearer ${apiKey}`, 'Content-Type': 'application/json' },\n  body: JSON.stringify({ model, messages: [{ role: 'user', content: 'ping' }], max_tokens: 1 }),\n});\nif (probe.status === 401 || probe.status === 403 || probe.status === 404) {\n  throw new Error(`LLM config invalid: ${probe.status} — fix --base-url/--api-key/--model before generating`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await callLLM(prompt, config);\n} catch (err) {\n  const m = err instanceof Error ? err.message : '';\n  if (/LLM API error \\((401|403)\\)/.test(m)) throw new Error('Re-authenticate: run gitnexus wiki --api-key <key>');\n  if (/LLM API error \\(404\\)/.test(m)) throw new Error('Check --base-url (append /v1) and --model name');\n  throw err;\n}","preventionTips":["Smoke-test the endpoint with a one-token request before launching full wiki generation","Keep base URL and model name paired in one provider profile so they can't drift","Rotate keys on a schedule and update ~/.gitnexus/config.json before expiry"],"tags":["llm","api-error","authentication","http-4xx","gitnexus"],"backgroundTag":"auth-api-error","analyzedSha":"52924ef12c2290ceee4612526a828ec4cdf2047f","analyzedAt":"2026-08-20T23:29:22.980Z","contentChangedAt":"2026-08-20T23:29:22.980Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}