router-for-me/CLIProxyAPI · error
kimi: empty access token in response
Error message
kimi: empty access token in response
What it means
The token endpoint returned HTTP 200 with no OAuth error field, but the access_token field is empty. The server claimed success yet delivered no usable credential, so the flow treats it as a protocol violation rather than success.
Source
Thrown at internal/auth/kimi/kimi.go:329
}
if oauthResp.Error != "" {
switch oauthResp.Error {
case "authorization_pending":
return nil, nil, true // Continue polling
case "slow_down":
return nil, nil, true // Continue polling (with increased interval handled by caller)
case "expired_token":
return nil, fmt.Errorf("kimi: device code expired"), false
case "access_denied":
return nil, fmt.Errorf("kimi: access denied by user"), false
default:
return nil, fmt.Errorf("kimi: OAuth error: %s - %s", oauthResp.Error, oauthResp.ErrorDescription), false
}
}
if oauthResp.AccessToken == "" {
return nil, fmt.Errorf("kimi: empty access token in response"), false
}
var expiresAt int64
if oauthResp.ExpiresIn > 0 {
expiresAt = time.Now().Unix() + int64(oauthResp.ExpiresIn)
}
return &KimiTokenData{
AccessToken: oauthResp.AccessToken,
RefreshToken: oauthResp.RefreshToken,
TokenType: oauthResp.TokenType,
ExpiresAt: expiresAt,
Scope: oauthResp.Scope,
}, nil, false
}
// RefreshToken exchanges a refresh token for a new access token.
func (c *DeviceFlowClient) RefreshToken(ctx context.Context, refreshToken string) (*KimiTokenData, error) {View on GitHub (pinned to 78f0c4079e)
Solutions
- Retry the login once — empty-payload 200s are usually transient server glitches
- If persistent, update CLIProxyAPI: this typically means Kimi changed the token response schema and the struct in kimi.go:299 must be adapted
- Capture the raw response body (log bodyBytes) to see which field actually holds the token
Defensive patterns
Strategy: validation
Try / catch
if err != nil && strings.Contains(err.Error(), "empty access token") {
// transient server glitch usually: retry login once; if persistent, schema changed upstream
} Prevention
- Retry once before escalating
- Log raw bodies to detect schema drift
- Track Kimi release notes for token endpoint changes
When it happens
Trigger: Moonshot-side change where success responses use a different field name (e.g. token moved to data.access_token), a partial response, or an A/B server behavior returning 200 with an empty payload.
Common situations: Upstream API contract changes after a Kimi release (parsing struct in kimi.go needs updating), rare server glitches, response mangled by intermediaries.
Related errors
- kimi: failed to create device code request: %w
- kimi: device code request failed: %w
- kimi: failed to read device code response: %w
- kimi: device code request failed with status %d: %s
- kimi: failed to parse device code response: %w
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/385738263801f9b7.
Report an issue: GitHub.