can1357/oh-my-pi · error · AIError.OAuthError
Kimi token refresh failed: ${response.status}${description}
Error message
Kimi token refresh failed: ${response.status}${description} What it means
Thrown by refreshKimiToken when the OAuth token refresh POST to Kimi returns a non-ok HTTP status. The error includes the HTTP status and any error_description Kimi returned, and is classified kind='token-refresh' with the status attached. It means the stored refresh token could not be exchanged for a new access token.
Source
Thrown at packages/ai/src/registry/oauth/kimi.ts:308
*/
export async function refreshKimiToken(refreshToken: string): Promise<OAuthCredentials> {
const response = await fetch(`${resolveOAuthHost()}/api/oauth/token`, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
...getKimiCommonHeaders(),
},
body: new URLSearchParams({
grant_type: "refresh_token",
refresh_token: refreshToken,
client_id: CLIENT_ID,
}),
});
if (!response.ok) {
const payload = (await response.json().catch(() => undefined)) as TokenResponse | undefined;
const description = payload?.error_description ? `: ${payload.error_description}` : "";
throw new AIError.OAuthError(`Kimi token refresh failed: ${response.status}${description}`, {
kind: "token-refresh",
provider: "kimi",
status: response.status,
});
}
const payload = (await response.json()) as TokenResponse;
return parseTokenPayload(payload, refreshToken);
}
View on GitHub (pinned to 9690622007)
Solutions
- Re-run the Kimi login flow (loginKimi()) to obtain fresh access/refresh tokens
- Clear cached Kimi credentials for this tool before re-authenticating to avoid stale tokens
- Check the embedded HTTP status: 400/401 means the refresh token is bad (must re-login); 5xx means retry later
- Update the CLI if Kimi changed its OAuth client configuration
Example fix
// before: assume refresh always works
const session = await getKimiSession();
// after: fall back to full re-login on refresh failure
let session;
try {
session = await refreshKimiToken(stored.refresh);
} catch (e) {
if (e instanceof AIError.OAuthError && e.kind === 'token-refresh') {
session = await loginKimi();
} else throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
// before calling, check the stored refresh token is present and not obviously stale
if (!stored?.refresh || Date.now() > stored.expires + 30 * 24 * 3600 * 1000) {
await loginKimi(); // refresh token likely expired/revoked — re-auth up front
} Try / catch
try {
session = await refreshKimiToken(stored.refresh);
} catch (e) {
if (e instanceof AIError.OAuthError && e.kind === 'token-refresh') {
if (e.status && e.status >= 500) {
// transient: back off and retry the refresh
} else {
session = await loginKimi(); // 4xx: full re-auth required
}
} else throw e;
} Prevention
- Re-authenticate proactively when refresh tokens near expiry
- Don't share/copy credential caches between machines
- Catch token-refresh errors and fall back to interactive login instead of crashing
- After revoking access in Kimi settings, expect to re-login
When it happens
Trigger: The stored refresh token is expired or revoked (Kimi refresh tokens have limited lifetimes); the refresh token was invalidated because the user logged out elsewhere or re-authorized; Kimi returns 400/401 for a malformed or unknown refresh_token; transient 5xx from Kimi's token endpoint.
Common situations: Long-lived sessions where the refresh token expired; user revoking the app in Kimi account settings; copying auth state between machines so tokens mismatch; Kimi rotating client credentials in a CLI update making old grants invalid.
Related errors
- Kimi device flow failed: ${error ?? response.status}${descri
- OAuth refresh did not produce a usable credential for provid
- OAuth provider "${provider}" does not support token refresh
- Antigravity credentials missing projectId
- Google Cloud credentials missing projectId
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/8fb272236a58dc92.
Report an issue: GitHub.