decolua/9router · error · Error
${data.error_description || data.error}
Error message
${data.error_description || data.error} What it means
The final catch-all branch of the pollAccessToken() poll loop: GitHub returned an error code that is not authorization_pending, slow_down, expired_token, or access_denied. The library throws the raw `error_description` or `error` from GitHub's JSON response. Known GitHub device-flow errors landing here include `unsupported_grant_type`, `incorrect_client_credentials`, `incorrect_device_code`, and `device_flow_disabled`.
Source
Thrown at src/lib/oauth/services/github.js:97
token_type: data.token_type,
scope: data.scope,
};
} else if (data.error === "authorization_pending") {
// Continue polling
continue;
} else if (data.error === "slow_down") {
// Increase polling interval
interval += 5000;
continue;
} else if (data.error === "expired_token") {
spinner.fail("Device code expired. Please try again.");
throw new Error("Device code expired");
} else if (data.error === "access_denied") {
spinner.fail("Access denied by user.");
throw new Error("Access denied");
} else {
spinner.fail("Failed to get access token.");
throw new Error(data.error_description || data.error);
}
}
}
/**
* Get Copilot token using GitHub access token
*/
async getCopilotToken(accessToken) {
const response = await fetch(`${GITHUB_CONFIG.copilotTokenUrl}`, {
headers: {
Authorization: `Bearer ${accessToken}`, // GitHub API typically uses Bearer
Accept: "application/json",
"X-GitHub-Api-Version": GITHUB_CONFIG.apiVersion,
"User-Agent": GITHUB_CONFIG.userAgent,
},
});
if (!response.ok) {View on GitHub (pinned to 90b52e06ff)
Solutions
- Restart the full authenticate() flow so a fresh device_code is issued instead of reusing an old one.
- Check the thrown message: `incorrect_client_credentials`/`device_flow_disabled` means GITHUB_CONFIG.clientId or the OAuth app's device-flow setting is wrong — fix the config or app settings.
- Confirm no proxy is rewriting responses from github.com (compare with curl).
- If the message is empty, patch to log the full `data` payload for diagnosis.
Example fix
// before
throw new Error(data.error_description || data.error);
// after
throw new Error(`Device flow error: ${data.error_description || data.error} (raw: ${JSON.stringify(data)})`); Defensive patterns
Strategy: try-catch
Type guard
function isKnownPollError(data) {
return ['authorization_pending','slow_down','expired_token','access_denied'].includes(data?.error);
} Try / catch
try {
const auth = await service.authenticate();
} catch (err) {
if (err.message === 'Access denied' || err.message === 'Device code expired') throw err; // known, actionable
if (err.message.startsWith('GitHub authentication failed')) {
console.error(`Unrecognized device-flow error: ${err.message}. Restart the flow with a fresh device code; if it persists, check client_id / device-flow app settings.`);
}
throw err;
} Prevention
- Always issue a fresh device_code per attempt — reusing codes produces incorrect_device_code.
- Validate the OAuth app has device flow enabled and the client_id is correct before shipping config.
- Log the full poll response payload when an unknown error appears so the GitHub error code is captured.
- Wrap the outer wrapper to preserve `{ cause }` so the original poll error isn't lost.
When it happens
Trigger: pollAccessToken() received an unrecognized OAuth error payload from https://github.com/login/oauth/access_token — e.g. a wrong or reused device_code (`incorrect_device_code`), an invalid client_id (`incorrect_client_credentials`), or a malformed grant request (`unsupported_grant_type`).
Common situations: The device_code was reused from a previous expired attempt; GITHUB_CONFIG.clientId is wrong or the OAuth app has device flow disabled; a proxy mutated the response so `data.error` holds something unexpected.
Related errors
- `Device code request failed: ${error}`
- Device code expired
- Access denied
- GitHub authentication failed: ${error.message}
- No Zed organization selected
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/ce5f8e65fcb59eae.
Report an issue: GitHub.