decolua/9router · error · Error
GitHub API error: ${error}
Error message
GitHub API error: ${error} What it means
After fetching the copilot_internal/user usage API, the library checks response.ok; when the upstream returns a non-2xx status it reads the body text and throws 'GitHub API error: <body>'. This surfaces upstream HTTP failures (401/403/404/5xx) with the raw upstream error payload embedded in the message.
Source
Thrown at open-sse/services/usage/github.js:39
if (!accessToken) {
throw new Error("No GitHub access token available. Please re-authorize the connection.");
}
// copilot_internal/user API requires GitHub OAuth token, not copilotToken
const response = await proxyAwareFetch(U("github").url, {
headers: {
"Authorization": `token ${accessToken}`,
"Accept": "application/json",
"X-GitHub-Api-Version": GITHUB_CONFIG.apiVersion,
"User-Agent": GITHUB_CONFIG.userAgent,
"Editor-Version": "vscode/1.100.0",
"Editor-Plugin-Version": "copilot-chat/0.26.7",
},
}, proxyOptions);
if (!response.ok) {
const error = await response.text();
throw new Error(`GitHub API error: ${error}`);
}
const data = await response.json();
// Handle different response formats (paid vs free)
if (data.quota_snapshots) {
// Paid plan format
const snapshots = data.quota_snapshots;
const resetAt = parseResetTime(data.quota_reset_date);
return {
plan: data.copilot_plan,
resetDate: data.quota_reset_date,
quotas: {
chat: { ...formatGitHubQuotaSnapshot(snapshots.chat), resetAt },
completions: { ...formatGitHubQuotaSnapshot(snapshots.completions), resetAt },
premium_interactions: { ...formatGitHubQuotaSnapshot(snapshots.premium_interactions), resetAt },
},View on GitHub (pinned to 90b52e06ff)
Solutions
- Read the embedded body in the message — a 401/403 means re-authorize the GitHub connection to mint a new accessToken
- Confirm the account still has an active Copilot subscription/entitlement
- Retry after backoff if the body indicates 429 or a 5xx outage
- Check GitHub status (githubstatus.com) if errors are widespread
Example fix
// before
const usage = await getGitHubUsage(staleToken, data, proxy);
// after
try {
const usage = await getGitHubUsage(staleToken, data, proxy);
} catch (e) {
if (/GitHub API error: .*401|Bad credentials/i.test(e.message)) await reauthorizeGitHub(account);
throw e;
} Defensive patterns
Strategy: retry
Validate before calling
// No pre-call check can detect upstream status; ensure token freshness first const tokenAge = Date.now() - (account.tokenObtainedAt || 0); if (tokenAge > 12 * 3600 * 1000) await reauthorizeGitHub(account);
Try / catch
try {
usage = await getGitHubUsage(token, data, proxy);
} catch (e) {
const m = /GitHub API error: (.*)/.exec(e.message);
if (m && /429|50[023]/.test(m[1])) {
await sleep(backoff); return getGitHubUsage(token, data, proxy);
}
if (/401|Bad credentials/.test(m?.[1] || "")) await reauthorizeGitHub(account);
throw e;
} Prevention
- Poll the usage endpoint at a modest interval to avoid 429
- Re-authorize on 401/403 instead of retrying with the same token
- Watch GitHub status for 5xx clusters
- Surface the embedded upstream body to users for diagnosis
When it happens
Trigger: The copilot_internal/user request returns a non-OK HTTP status: expired/revoked accessToken (401), token lacking Copilot entitlement (403/404), GitHub API outage (5xx), or rate-limited request (429).
Common situations: GitHub token revoked or expired after a password change; a fine-grained/PAT token without the right scopes; GitHub incident/outage; heavy polling of the usage endpoint hitting secondary rate limits.
Related errors
- qoder PAT exchange failed: ${res.status} ${text.slice(0, 200
- No GitHub access token available. Please re-authorize the co
- Failed to export database
- Missing API key
- Invalid API key
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/fa82b186e304b47b.
Report an issue: GitHub.