chatboxai/chatbox · error · Error
${response.status} ${response.statusText}: ${text}
Error message
${response.status} ${response.statusText}: ${text} What it means
Generic HTTP failure thrown by the internal fetchJson() helper used by both startDeviceFlow() (POST /login/device/code) and waitForToken() (POST /login/oauth/access_token). The message combines status, statusText, and body so the underlying GitHub response (e.g. 404, 422 JSON, rate-limit text) is visible. Because GitHub returns pending/slow_down as HTTP 200 with an error field, a throw from fetchJson always indicates a genuine HTTP-level failure, not the expected polling states.
Source
Thrown at src/main/oauth/providers/github-copilot.ts:23
const CLIENT_ID = decode('T3YyM2xpOHR3ZVF3Nm9kV1FlYno=')
const GITHUB_DOMAIN = 'github.com'
// Pending device flow state
let pendingDeviceCode: string | null = null
let pendingInterval = 5
function getUrls(domain: string) {
return {
deviceCodeUrl: `https://${domain}/login/device/code`,
accessTokenUrl: `https://${domain}/login/oauth/access_token`,
}
}
async function fetchJson(url: string, init: RequestInit): Promise<unknown> {
const response = await fetch(url, init)
if (!response.ok) {
const text = await response.text()
throw new Error(`${response.status} ${response.statusText}: ${text}`)
}
return response.json()
}
export const githubCopilotOAuthProvider: DeviceCodeOAuthProvider = {
kind: 'device-code',
providerId: 'github-copilot',
name: 'GitHub Copilot',
async startDeviceFlow() {
const urls = getUrls(GITHUB_DOMAIN)
const data = (await fetchJson(urls.deviceCodeUrl, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({View on GitHub (pinned to 81571269ad)
Solutions
- Parse the leading status code from the message — 404/422 on /login/device/code usually means a bad CLIENT_ID or GITHUB_DOMAIN.
- For 'expired_token' from the polling endpoint, restart with startDeviceFlow() to get a fresh device_code.
- For 429, respect Retry-After and back off; for 5xx, retry with jitter.
- Confirm the CLIENT_ID decode still yields the expected GitHub OAuth App id.
Example fix
// before
const data = (await fetchJson(urls.deviceCodeUrl, init)) as {...}
// after
let data
try {
data = (await fetchJson(urls.deviceCodeUrl, init)) as {...}
} catch (e) {
const msg = String(e)
if (/\b404\b|\b422\b/.test(msg)) throw new Error('GitHub rejected the client_id or domain. Check CLIENT_ID.')
throw e
} Defensive patterns
Strategy: try-catch
Type guard
function isHttpFailure(e: unknown): e is Error {
return e instanceof Error && /^\d{3}\s+/.test(e.message)
} Try / catch
try {
return await provider.startDeviceFlow()
} catch (e) {
const msg = String(e)
if (/\b429\b/.test(msg)) {
await new Promise(r => setTimeout(r, backoffMs()))
return await provider.startDeviceFlow()
}
if (/\b404\b|\b422\b/.test(msg)) throw new Error('GitHub rejected CLIENT_ID or domain — check config.')
throw e
} Prevention
- Verify the base64 CLIENT_ID decodes to the expected GitHub OAuth App id after every release.
- Keep GITHUB_DOMAIN as 'github.com' unless GitHub documents otherwise.
- Differentiate HTTP failures (this error) from polling application errors (raw.error) when surfacing to users.
When it happens
Trigger: Invalid or revoked CLIENT_ID constant; wrong GITHUB_DOMAIN; the device_code has expired (422 'expired_token') or is invalid; rate limited (429); GitHub API outage (5xx); malformed request body (422 unsupported_grant_type).
Common situations: CLIENT_ID base64 constant drifted after GitHub rotated it; user waited past the device-code lifetime then the polling hit an expired device_code; corporate proxy returning a captive-portal HTML page (status 200 but non-JSON, or a 4xx).
Related errors
- Device flow failed: ${raw.error}
- Device flow timed out
- MiniMax authorization failed: ${text}
- Qwen device authorization failed: ${text}
- Qwen OAuth failed: ${payload.error_description || payload.er
AI-assisted analysis of chatboxai/chatbox@81571269ad (2026-08-12).
Data as JSON: /api/errors/b215acad38e41867.
Report an issue: GitHub.