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

  1. Retry the login once — empty-payload 200s are usually transient server glitches
  2. If persistent, update CLIProxyAPI: this typically means Kimi changed the token response schema and the struct in kimi.go:299 must be adapted
  3. 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

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


AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15). Data as JSON: /api/errors/385738263801f9b7. Report an issue: GitHub.