{"record":{"id":"b83ab4873958b2ba","repo":"chatboxai/chatbox","slug":"status-code-res-status","errorCode":null,"errorMessage":"Status Code ${res.status}","messagePattern":"Status Code (.+?)","errorType":"http","errorClass":"ApiError","httpStatus":null,"severity":"error","filePath":"src/renderer/utils/request.ts","lineNumber":72,"sourceCode":"  const { signal, retry = 3, useProxy = false, body, method } = options\n  let requestUrl = url\n  const headers = buildHeaders(options, url)\n\n  if (useProxy && !isLocalHost(url) && platform.type !== 'mobile') {\n    const version = await platform.getVersion()\n    headers.set('CHATBOX-VERSION', version || 'unknown')\n    requestUrl = 'https://cors-proxy.chatboxai.app/proxy-api/completions'\n  }\n\n  const makeRequest = async () => {\n    if (platform.type === 'mobile' && useProxy) {\n      return handleMobileRequest(requestUrl, method, headers, body, signal)\n    }\n\n    const res = await fetch(requestUrl, { method, headers, body, signal })\n    if (!res.ok) {\n      const err = await res.text().catch(() => null)\n      throw new ApiError(`Status Code ${res.status}`, err ?? undefined)\n    }\n    return res\n  }\n\n  return retryRequest(makeRequest, retry, requestUrl)\n}\n\nexport const apiRequest = {\n  async post(\n    url: string,\n    headers: Record<string, string>,\n    body: RequestInit['body'],\n    options?: Partial<RequestOptions>\n  ) {\n    return doRequest(url, { ...options, method: 'POST', headers, body })\n  },\n\n  async get(url: string, headers: Record<string, string>, options?: Partial<RequestOptions>) {","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/chatboxai/chatbox/blob/81571269addb6bafb589a920b2883f1e1e084fd1/src/renderer/utils/request.ts#L54-L90","documentation":"Thrown by the standard (non-mobile) fetch path when res.ok is false: an ApiError is constructed with `Status Code ${res.status}` and, when readable, the response body as responseBody. This is the desktop/web equivalent of the mobile status-code error (228) and is the single failure exit for fetch-based provider calls, wrapped by retryRequest.","triggerScenarios":"fetch resolves with a non-OK status (res.ok === false, i.e. status outside 200–299). The body is read via res.text() (null on read failure). The error propagates through retryRequest, which may re-invoke makeRequest up to the retry count before this error reaches the caller.","commonSituations":"Provider returned 401 (bad key), 429 (rate limit), 5xx (server error); CORS error surfaced as a network failure (these usually reject fetch, but opaque responses can land here); self-signed cert / TLS issue; provider deprecated an endpoint (404); upstream gateway timeout (504).","solutions":["Read ApiError.responseBody — most providers put a JSON error object there with a specific code/message that points at the fix.","Match on statusCode: 401/403 → rotate/fix the API key; 429 → reduce request rate / implement backoff; 5xx → retry then check provider status page.","For CORS/TLS errors, route the request through the cors-proxy (set useProxy) or fix the server's CORS headers.","Verify the request URL and CHATBOX-VERSION header — a wrong apiPath or stale version can yield 404/400."],"exampleFix":"// before\nconst res = await fetch(requestUrl, { method, headers, body, signal })\nif (!res.ok) {\n  const err = await res.text().catch(() => null)\n  throw new ApiError(`Status Code ${res.status}`, err ?? undefined)\n}\n// after — parse the body so callers get structured detail\nconst res = await fetch(requestUrl, { method, headers, body, signal })\nif (!res.ok) {\n  const err = await res.text().catch(() => null)\n  throw new ApiError(`Status Code ${res.status}`, err ?? undefined, res.status)\n}","handlingStrategy":"retry","validationCode":"// Pre-flight header/url sanity check before fetch.\nfunction assertRequestShape(url: string, headers: Record<string,string>): void {\n  new URL(url) // throws on malformed\n  if (!headers['Authorization'] && !headers['CHATBOX-VERSION']) {\n    console.warn('Request may lack auth/version headers')\n  }\n}","typeGuard":"function isApiError(e: unknown): e is ApiError {\n  return e instanceof ApiError\n}","tryCatchPattern":"try {\n  return await apiRequest.post(url, headers, body)\n} catch (e) {\n  if (e instanceof ApiError) {\n    if (e.statusCode === 429) return retryWithBackoff(() => apiRequest.post(url, headers, body))\n    if (e.statusCode === 401) rotateApiKey()\n    if (e.statusCode && e.statusCode >= 500) return retryWithBackoff(() => apiRequest.post(url, headers, body))\n  }\n  throw e\n}","preventionTips":["Parse ApiError.responseBody as JSON when possible to extract provider-specific error codes.","Set sensible retry counts on retryRequest so transient 5xx/429 are retried automatically.","Validate apiHost and CHATBOX-VERSION before requests — wrong values yield 404/400."],"tags":["network","fetch","http-status","provider"],"backgroundTag":null,"analyzedSha":"81571269addb6bafb589a920b2883f1e1e084fd1","analyzedAt":"2026-08-12T21:51:44.981Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}