Wei-Shaw/sub2api · error

HTTP error! status: ${response.status}

Error message

HTTP error! status: ${response.status}

What it means

In frontend/src/components/admin/account/AccountTestModal.vue:896 (the admin variant of the test modal), the streaming fetch checks response.ok and throws `HTTP error! status: ${response.status}` for any non-2xx. This variant sends an ADMIN_UI_REQUEST_HEADER: '1' marker, so failures commonly relate to admin authentication/authorization rather than the model itself. The response body's error detail is discarded.

Source

Thrown at frontend/src/components/admin/account/AccountTestModal.vue:896

    }

    // Use the configured API base; EventSource does not support POST.
    const url = buildApiUrl(`/admin/accounts/${props.account.id}/test`)

    // Use fetch with streaming for SSE since EventSource doesn't support POST
    const response = await fetch(url, {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${localStorage.getItem('auth_token')}`,
        'Content-Type': 'application/json',
        [ADMIN_UI_REQUEST_HEADER]: '1'
      },
      body: JSON.stringify(requestBody),
      signal: abortController.signal
    })

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`)
    }

    const reader = response.body?.getReader()
    if (!reader) {
      throw new Error(t('admin.accounts.grok.noResponseBody'))
    }

    const decoder = new TextDecoder()
    let buffer = ''

    while (true) {
      const { done, value } = await reader.read()
      if (done) break

      buffer += decoder.decode(value, { stream: true })
      const lines = buffer.split('\n')
      buffer = lines.pop() || ''

View on GitHub (pinned to 073e92d171)

Solutions

  1. Parse the response body for an error message before throwing, mirroring the i18n approach used for noResponseBody.
  2. On 401/403, redirect to admin re-login and stop the spinner cleanly.
  3. Ensure ADMIN_UI_REQUEST_HEADER is actually set on this request in the deployed environment (check proxy header forwarding).
  4. Add specific messages per status (401/403/429/5xx) instead of the generic template.

Example fix

// before
if (!response.ok) {
  throw new Error(`HTTP error! status: ${response.status}`)
}

// after
if (!response.ok) {
  const body = await response.json().catch(() => null)
  const msg = body?.error?.message || body?.message
  if (response.status === 401 || response.status === 403) {
    await reauthenticateAdmin()
    throw new Error(t('admin.accounts.grok.unauthorized'))
  }
  throw new Error(msg ? `${msg} (HTTP ${response.status})` : t('admin.accounts.grok.httpError', { status: response.status }))
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!localStorage.getItem('auth_token')) { redirectToAdminLogin(); } // before opening the admin test modal

Try / catch

try { await adminStreamTest(); }
catch (e) {
  const status = String(e?.message).match(/status: (\d+)$/)?.[1];
  if (status === '401' || status === '403') { await reauthenticateAdmin(); return; }
  showError(parseDetail(e));
}

Prevention

When it happens

Trigger: POST to the admin account-test URL returns 401 (admin token expired), 403 (non-admin user or missing ADMIN_UI_REQUEST_HEADER), 400 (invalid requestBody/model_id), or 5xx (upstream provider failure). The thrown message contains only the status number.

Common situations: Admin session expiring while the modal is open; the admin request header stripped by a proxy or missing in a custom deployment; testing an account whose upstream key is dead; gateway timeout on slow model responses (504).

Related errors


AI-assisted analysis of Wei-Shaw/sub2api@073e92d171 (2026-08-15). Data as JSON: /api/errors/b9b9d2641a149817. Report an issue: GitHub.