{"record":{"id":"3ea7d57a3027a55c","repo":"koodo-reader/koodo-reader","slug":"http-response-status-response-body-substring","errorCode":null,"errorMessage":"HTTP ${response.status}: ${response.body.substring(0, 200)}","messagePattern":"HTTP (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/containers/settings/aiSetting/component.tsx","lineNumber":206,"sourceCode":"        ? endpoint + \"chat/completions\"\n        : endpoint + \"/chat/completions\";\n      const response = await aiRequest(\n        chatEndpoint,\n        \"POST\",\n        {\n          \"Content-Type\": \"application/json\",\n          Authorization: `Bearer ${apiKey}`,\n        },\n        JSON.stringify({\n          model: modelId,\n          messages: [\n            { role: \"user\", content: \"Hi, just testing. Reply with OK.\" },\n          ],\n          max_tokens: 10,\n        })\n      );\n      if (!response.ok) {\n        throw new Error(\n          `HTTP ${response.status}: ${response.body.substring(0, 200)}`\n        );\n      }\n      const data = JSON.parse(response.body);\n      const reply =\n        data.choices?.[0]?.message?.content ||\n        JSON.stringify(data).substring(0, 100);\n      this.setState({ testResult: \"success\" });\n      toast.success(this.props.t(\"Test successful\") + \": \" + reply);\n    } catch (e: any) {\n      this.setState({ testResult: \"fail\" });\n      toast.error(this.props.t(\"Test failed\") + \": \" + e.message);\n    } finally {\n      this.setState({ isTesting: false });\n    }\n  };\n\n  handleSave = async () => {","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/koodo-reader/koodo-reader/blob/7d40df41e05cfc0a341fe9ea66a12819b522b7fa/src/containers/settings/aiSetting/component.tsx#L188-L224","documentation":"The AI connectivity test in AISetting sends a tiny chat completion (\"Reply with OK.\", max_tokens 10) via aiRequest and throws `HTTP <status>: <first 200 chars of body>` when it fails. Including the response body snippet surfaces provider-specific errors like 'invalid_api_key' or 'model_not_found' directly in the thrown message.","triggerScenarios":"Running the connection test for a chat provider; the completion endpoint returns 401 (bad key), 404 (wrong path/model), 400 (malformed request or unsupported parameter), 429 (quota/rate limit), or 5xx, with the provider's error JSON in the body.","commonSituations":"API key invalid/revoked or billing not enabled (OpenAI 429 insufficient_quota); selected model name not available to the account (404 model_not_found); base URL pointing to /v1/chat/completions on a server that uses another route; request blocked by proxy returning HTML (visible in the body snippet).","solutions":["Read the body snippet in the error message — it usually names the exact problem (invalid_api_key, model_not_found, insufficient_quota).","401/403: re-enter the API key and confirm it is active with billing/quota set up.","404 or model error: pick a model the key can access; verify the chat completions endpoint path.","429: check quota/usage on the provider dashboard or wait for the rate-limit window.","Verify network reachability (VPN/proxy/firewall) if the body snippet is HTML instead of JSON."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if (!state.apiKey.trim()) throw new Error(\"API key required before testing connection\");\nif (!provider.chatEndpoint || !/^https?:\\/\\//.test(provider.chatEndpoint)) throw new Error(\"Chat endpoint missing or invalid\");","typeGuard":null,"tryCatchPattern":"try {\n  const response = await aiRequest(provider.chatEndpoint, \"POST\", headers, JSON.stringify(payload));\n  if (!response.ok) {\n    throw new Error(`HTTP ${response.status}: ${response.body.substring(0, 200)}`);\n  }\n  const data = JSON.parse(response.body);\n} catch (err) {\n  toast.error(t(\"Connection test failed\") + \": \" + err.message);\n}","preventionTips":["Read the body snippet in the error — provider messages name the root cause","Check provider dashboard for quota/billing before retesting","Confirm the model name is available to your account","Watch for HTML bodies indicating a proxy/firewall interception"],"tags":["network","http","api","ai-provider","authentication"],"backgroundTag":"http-non-2xx-response","analyzedSha":"7d40df41e05cfc0a341fe9ea66a12819b522b7fa","analyzedAt":"2026-08-29T01:41:43.691Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}