coleam00/Archon · info · DeviceFlowError

aborted

aborted

Error message

Device flow polling was aborted

What it means

pollDeviceFlow loops until the user authorizes the device. Before each sleep it checks opts.signal; if the caller aborted the poll, it throws DeviceFlowError with code 'aborted' so callers can distinguish intentional cancellation from auth failure.

Source

Thrown at packages/core/src/github-auth/device-flow.ts:117

const defaultSleep = (ms: number): Promise<void> => new Promise(resolve => setTimeout(resolve, ms));

/**
 * Step 2: poll until the user authorizes. Handles `authorization_pending`
 * (keep waiting) and `slow_down` (back off using the server-supplied interval).
 * Any other `error` is terminal and thrown as a DeviceFlowError.
 */
export async function pollDeviceFlow(
  clientId: string,
  deviceCode: string,
  intervalSeconds: number,
  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' }

View on GitHub (pinned to 0773b97458)

Solutions

  1. Treat code 'aborted' as an expected cancellation, not an auth failure — return to the login prompt
  2. Only abort when you actually intend to cancel; pass signal: undefined otherwise
  3. Wrap the poll in try/catch that special-cases aborted and restarts the device flow on demand

Example fix

// before
const token = await pollDeviceFlow(clientId, data, 5, { signal });
// after
try {
  const token = await pollDeviceFlow(clientId, data, 5, { signal });
} catch (e) {
  if (e instanceof DeviceFlowError && e.code === 'aborted') return null;
  throw e;
}
Defensive patterns

Strategy: try-catch

Try / catch

try { return await pollDeviceFlow(clientId, deviceCode, interval, { signal }); } catch (e) { if (e instanceof DeviceFlowError && e.code === 'aborted') return null; throw e; }

Prevention

When it happens

Trigger: Calling pollDeviceFlow with an AbortSignal and aborting it (e.g. user cancels login, UI timeout, shutdown) while polling is still pending.

Common situations: User closes the browser before entering the code; CLI cancelled with Ctrl-C mapped to an AbortController; server shutting down mid-login; application-level login timeout.

Related errors


AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01). Data as JSON: /api/errors/68fe915029d63735. Report an issue: GitHub.