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

  1. Re-run loginKimi() and approve the authorization prompt in the browser this time
  2. Verify you are completing the consent in the same browser session within the code's expiry window
  3. If denials are unexpected, check for security extensions/policies blocking OAuth consent pages
  4. 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

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


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/792094273d317f77. Report an issue: GitHub.