chatboxai/chatbox · error · ApiError

Status Code ${response.status}

Error message

Status Code ${response.status}

What it means

Thrown by the mobile HTTP shim (CapacitorHttp) after a request completes: when response.status is 0 (no response / CORS / native failure), < 200, or >= 400, an ApiError is constructed with the raw body as its message payload and the numeric status. It is the single failure exit for all mobile network calls routed through this shim.

Source

Thrown at src/renderer/utils/mobile-request.ts:91

        },
      })
    } catch (err) {
      console.warn('Native streaming unavailable, falling back', err)
    }
  }

  const response = await CapacitorHttp.request({
    url,
    method,
    headers: headerObj,
    data: body,
    responseType: 'text',
  })

  const rawData = typeof response.data === 'string' ? response.data : JSON.stringify(response.data)
  // Treat status 0 or < 200 as errors, in addition to >= 400
  if (response.status === 0 || response.status < 200 || response.status >= 400) {
    throw new ApiError(`Status Code ${response.status}`, rawData, response.status)
  }
  const responseData = rawData

  if (isStreaming) {
    const stream = new ReadableStream({
      start(controller) {
        controller.enqueue(new TextEncoder().encode(responseData))
        controller.close()
      },
    })
    return new Response(stream, {
      status: response.status,
      headers: { ...response.headers, 'Content-Type': 'text/event-stream' },
    })
  }

  return new Response(responseData, {
    status: response.status,

View on GitHub (pinned to 81571269ad)

Solutions

  1. Read the ApiError.statusCode — 401/403 → fix API key/headers; 429 → back off and retry; 5xx → provider outage, retry with exponential backoff; 0 → check device connectivity and ATS/CORS config.
  2. Inspect ApiError.responseBody for the server's actual error message — HTML bodies typically indicate a gateway/proxy error, not an API error.
  3. For self-hosted providers, ensure the endpoint sends permissive CORS headers and HTTPS (ATS blocks plain HTTP on iOS).
  4. If status is consistently 0 on Android, verify the network_security_config / cleartext policy permits the host.

Example fix

// before
if (response.status === 0 || response.status < 200 || response.status >= 400) {
  throw new ApiError(`Status Code ${response.status}`, rawData, response.status)
}
// after — distinguish no-response from HTTP error for clearer UX
if (response.status === 0) {
  throw new ApiError('No response (network/CORS/ATS failure)', rawData, 0)
}
if (response.status < 200 || response.status >= 400) {
  throw new ApiError(`Status Code ${response.status}`, rawData, response.status)
}
Defensive patterns

Strategy: retry

Validate before calling

// Pre-validate the URL scheme and connectivity before issuing the CapacitorHttp call.
function isMobileRequestLikelyToSucceed(url: string): boolean {
  try {
    const u = new URL(url)
    return u.protocol === 'https:' || u.protocol === 'http:'
  } catch { return false }
}

Type guard

function isApiErrorWithStatus(e: unknown): e is ApiError & { statusCode: number } {
  return e instanceof ApiError && typeof (e as any).statusCode === 'number'
}

Try / catch

try {
  return await mobileRequest(url, opts)
} catch (e) {
  if (e instanceof ApiError && typeof e.statusCode === 'number') {
    if (e.statusCode === 0) showUser('Network unavailable. Check your connection.')
    else if (e.statusCode >= 500) return retryWithBackoff(() => mobileRequest(url, opts))
    else if (e.statusCode === 401) rotateApiKey()
  }
  throw e
}

Prevention

When it happens

Trigger: CapacitorHttp.request resolves with a non-2xx status: server returns 4xx/5xx; status 0 from a DNS/CORS/native-network failure; rawData is the stringified body (HTML error page, JSON error, or empty). The thrown ApiError carries rawData as responseBody and response.status as statusCode.

Common situations: Provider endpoint down (502/503/504); invalid API key (401); rate limit (429); mobile platform blocking the URL via App Transport Security; CORS misconfiguration on a self-hosted endpoint; offline/no network giving status 0; server returning HTML instead of JSON.

Related errors


AI-assisted analysis of chatboxai/chatbox@81571269ad (2026-08-12). Data as JSON: /api/errors/1e8bd82e35ccaf87. Report an issue: GitHub.