coleam00/Archon · info
Login cancelled
Error message
Login cancelled
What it means
postTokenRequest in packages/core/src/credentials/openai-oauth.ts:175 rethrows caller cancellation as 'Login cancelled'. When the fetch to OPENAI_TOKEN_URL fails and the caller-supplied AbortSignal (the bridge session's abort signal) is aborted, the error is normalized to this message instead of a misleading network error. It means the token exchange/refresh was cancelled, e.g. by cancelOAuth, supersession, or session expiry.
Source
Thrown at packages/core/src/credentials/openai-oauth.ts:175
operation: 'exchange' | 'refresh',
signal?: AbortSignal
): Promise<OpenAiTokenResponse> {
let response: Response;
try {
response = await fetch(OPENAI_TOKEN_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body,
// The 30s ceiling applies ALWAYS — combined with the caller's session
// signal when present. Without it, a hung token endpoint would leave a
// bridge login reporting `pending` for the session's full 10-minute TTL.
signal: signal
? AbortSignal.any([signal, AbortSignal.timeout(30_000)])
: AbortSignal.timeout(30_000),
});
} catch (error) {
if (signal?.aborted) {
throw new Error('Login cancelled');
}
if (error instanceof Error && error.name === 'TimeoutError') {
throw new Error(`OpenAI token ${operation} request timed out.`);
}
throw new Error(
`OpenAI token ${operation} request failed: ${error instanceof Error ? error.message : String(error)}`
);
}
if (!response.ok) {
// Strip the error body down to the OAuth `error` code: this message flows
// into the bridge's session.detail (and on to the browser/CLI), and OpenAI
// error bodies can carry account identifiers. Never include the raw body.
const text = await response.text().catch(() => '');
let errorCode = '';
try {
const parsed = JSON.parse(text) as { error?: unknown };
if (typeof parsed.error === 'string') {
errorCode = parsed.error;View on GitHub (pinned to 0773b97458)
Solutions
- Nothing to fix — restart the login by calling startOAuth again after any cancellation.
- Avoid cancelling a login unless intended; be aware supersession also cancels in-flight token exchanges.
- Handle this message/flow in the UI as a normal cancel outcome, not a bug report.
Defensive patterns
Strategy: try-catch
Validate before calling
// Do not proceed when the session's abort signal is already aborted
if (session.abort.signal.aborted) {
throw new Error('Login already cancelled; start a new one.');
} Try / catch
try {
await exchangeOpenAiAuthorizationCode(code, verifier, signal);
} catch (e) {
if (e instanceof Error && e.message === 'Login cancelled') {
// Expected outcome of cancelOAuth/supersession/expiry — restart login if desired
return;
}
throw e;
} Prevention
- Treat this as the expected cancel path; log at info, not error.
- Design UI so cancel actions intentionally terminate pending exchanges.
- Remember supersession also cancels: don't fire a second login expecting the first to finish.
When it happens
Trigger: Calling cancelOAuth, starting a newer login that supersedes the session, or the session TTL expiring while the OpenAI token exchange fetch is in flight; the aborted fetch rejects and postTokenRequest maps it to 'Login cancelled'.
Common situations: User clicking 'Cancel' during login; a second login attempt superseding the first; a login left idle until TTL expiry while the token exchange was still pending.
Related errors
- aborted
- Provider '${provider}' does not support subscription login.
- Vendor '${vendor}' (Pi backend) has no env-based OAuth deliv
- OAuth state mismatch.
- Missing authorization code.
AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01).
Data as JSON: /api/errors/fad22a148704b0dc.
Report an issue: GitHub.