coleam00/Archon · error · DeviceFlowError
${result.code}
Error message
${result.code} What it means
When a single poll returns a terminal status other than 'pending' or 'slow_down' (e.g. authorization_pending expired, access_denied, bad_verification_code), pollDeviceFlow throws DeviceFlowError with GitHub's error code as the message.
Source
Thrown at packages/core/src/github-auth/device-flow.ts:129
opts: PollOptions = {}
): Promise<DeviceAccessToken> {
const sleep = opts.sleep ?? defaultSleep;
let interval = Math.max(1, intervalSeconds);
for (;;) {
if (opts.signal?.aborted) {
throw new DeviceFlowError('aborted', 'Device flow polling was aborted');
}
await sleep(interval * 1000);
const result = await pollDeviceFlowOnce(clientId, deviceCode);
if (result.status === 'authorized') return result.token;
if (result.status === 'pending') continue;
if (result.status === 'slow_down') {
// Honor the server's new interval, else keep the current. Floor at 1s so a
// malformed `interval: 0` can't turn this into a busy loop.
interval = Math.max(1, result.interval);
continue;
}
throw new DeviceFlowError(result.code);
}
}
/** Result of a single (non-blocking) device-flow poll. */
export type PollOnceResult =
| { status: 'pending' }
| { status: 'slow_down'; interval: number }
| { status: 'authorized'; token: DeviceAccessToken }
| { status: 'error'; code: string };
/**
* One non-blocking poll attempt. Used by the web endpoint (which polls from the
* browser) and internally by {@link pollDeviceFlow}'s blocking loop.
*/
export async function pollDeviceFlowOnce(
clientId: string,
deviceCode: string
): Promise<PollOnceResult> {View on GitHub (pinned to 0773b97458)
Solutions
- Restart startDeviceFlow to get a fresh device/user code and try again
- If code is access_denied, ask the user to approve the request next time
- If code is authorization_pending/expired, complete the login faster or raise the code lifetime
- Match on the specific code and surface a user-friendly message
Example fix
// before
const token = await pollDeviceFlow(clientId, data.device_code, 5);
// after
try {
const token = await pollDeviceFlow(clientId, data.device_code, 5);
} catch (e) {
if (e instanceof DeviceFlowError && e.code === 'authorization_pending') {
return startDeviceFlow(clientId); // fresh code
}
throw e;
} Defensive patterns
Strategy: retry
Try / catch
try { return await pollDeviceFlow(clientId, deviceCode, interval); } catch (e) { if (e instanceof DeviceFlowError && e.code === 'authorization_pending') return restartDeviceFlow(); throw e; } Prevention
- Show the user code with a visible countdown of its expiry to encourage quick entry
- Handle access_denied and expired codes by restarting startDeviceFlow
- Do not reuse a device_code after a terminal error
When it happens
Trigger: pollDeviceFlow's pollDeviceFlowOnce returns a status like 'denied' or 'expired' — the user clicked 'I do not authorize', the user code expired, or the wrong code was entered.
Common situations: User takes too long and the device code expires; user denies the authorization request; user types the wrong code; polling continues after the token was already consumed.
Related errors
- ${data.error}
- aborted
- Repository ${owner}/${repo} not found or is private. Check r
- Authentication failed for ${owner}/${repo}. ${authHint}
- Failed to clone ${owner}/${repo}: ${'message' in cloneResult
AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01).
Data as JSON: /api/errors/22005360e9701f28.
Report an issue: GitHub.