can1357/oh-my-pi · warning · AIError.OAuthError
Kimi device authorization denied
Error message
Kimi device authorization denied
What it means
Thrown during the Kimi OAuth device-authorization polling loop when Kimi's token endpoint returns error='access_denied', meaning the user explicitly denied the authorization request in the browser (or the consent page was closed/dismissed in a way Kimi treats as denial). The library maps it to AIError.OAuthError with kind='validation' since no retry can succeed. It is terminal for this login attempt; a fresh device code must be requested.
Source
Thrown at packages/ai/src/registry/oauth/kimi.ts:256
}
if (error === "slow_down") {
waitMs += 5000;
const retryAfter = typeof payload.interval === "number" ? payload.interval * 1000 : undefined;
if (retryAfter && retryAfter > waitMs) waitMs = retryAfter;
await scheduler.wait(waitMs, { signal });
continue;
}
if (error === "expired_token") {
throw new AIError.OAuthError("Kimi device authorization expired", {
kind: "validation",
provider: "kimi",
});
}
if (error === "access_denied") {
throw new AIError.OAuthError("Kimi device authorization denied", {
kind: "validation",
provider: "kimi",
});
}
const description = payload.error_description ? `: ${payload.error_description}` : "";
throw new AIError.OAuthError(`Kimi device flow failed: ${error ?? response.status}${description}`, {
kind: "polling",
provider: "kimi",
});
}
throw new AIError.OAuthError("Kimi device flow timed out", {
kind: "timeout",
provider: "kimi",
});
}
View on GitHub (pinned to 9690622007)
Solutions
- Re-run loginKimi() and approve the authorization prompt in the browser this time
- Verify you are completing the consent in the same browser session within the code's expiry window
- If denials are unexpected, check for security extensions/policies blocking OAuth consent pages
- If automating, do not auto-dismiss the consent URL printed by the CLI
Example fix
// before: user denies, login crashes mid-script
await loginKimi();
// after: handle denial and prompt again
try {
await loginKimi();
} catch (e) {
if (e instanceof AIError.OAuthError && e.message.includes('denied')) {
console.error('Authorization was denied. Please retry and click Approve.');
await loginKimi();
} else throw e;
} Defensive patterns
Strategy: try-catch
Try / catch
try {
await loginKimi();
} catch (e) {
if (e instanceof AIError.OAuthError && e.message === 'Kimi device authorization denied') {
// prompt the user to retry and approve
} else throw e;
} Prevention
- Instruct users before starting that they must click Approve in the browser
- Show the verification URL and code prominently and keep the process in the foreground
- Never auto-dismiss or script the consent page
When it happens
Trigger: loginKimi() starts the device flow and the user clicks 'Deny'/'Cancel' on Kimi's consent page instead of approving; the code is also reached if the consent page reports access_denied after the code expired or was already used.
Common situations: User gets cold feet or doesn't recognize the login request; shared machine where another person denies the prompt; corporate/security software auto-dismissing OAuth consent pages; user taking too long so the code expires and the page shows a denial-like error.
Related errors
- Kimi device flow failed: ${error ?? response.status}${descri
- Kimi device flow timed out
- Too many pending authorization requests. Please try again la
- Failed to initiate device authorization: ${initiateResponse.
- Kilo device authorization response missing required fields
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/792094273d317f77.
Report an issue: GitHub.