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

  1. Re-run the Kimi login flow (loginKimi()) to obtain fresh access/refresh tokens
  2. Clear cached Kimi credentials for this tool before re-authenticating to avoid stale tokens
  3. Check the embedded HTTP status: 400/401 means the refresh token is bad (must re-login); 5xx means retry later
  4. 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

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


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