router-for-me/CLIProxyAPI · error
failed to parse refresh response: %w
Error message
failed to parse refresh response: %w
What it means
The refresh endpoint returned 200 but the body failed json.Unmarshal into the expected token struct — syntactically invalid JSON, typically rewritten or truncated by an intermediary. Note that claims parsing of the ID token (ParseJWTToken) is deliberately non-fatal (logged as warning), so this error is purely about the outer response not being parseable JSON.
Source
Thrown at internal/auth/codex/openai_auth.go:257
body, errRead := io.ReadAll(resp.Body)
if errRead != nil {
return nil, fmt.Errorf("failed to read refresh response: %w", errRead)
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("token refresh failed with status %d: %s", resp.StatusCode, string(body))
}
var tokenResp struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
IDToken string `json:"id_token"`
TokenType string `json:"token_type"`
ExpiresIn int `json:"expires_in"`
}
if errUnmarshal := json.Unmarshal(body, &tokenResp); errUnmarshal != nil {
return nil, fmt.Errorf("failed to parse refresh response: %w", errUnmarshal)
}
// Extract account ID from ID token
claims, errParseJWT := ParseJWTToken(tokenResp.IDToken)
if errParseJWT != nil {
log.Warnf("Failed to parse refreshed ID token: %v", errParseJWT)
}
accountID := ""
email := ""
if claims != nil {
accountID = claims.GetAccountID()
email = claims.Email
}
return &CodexTokenData{
IDToken: tokenResp.IDToken,
AccessToken: tokenResp.AccessToken,View on GitHub (pinned to 78f0c4079e)
Solutions
- Log the raw body at debug level to see what was actually served.
- Remove the intermediary for the auth domain (proxy bypass rule).
- Retry after confirming clean network path; persistent malformed 200s point at the middlebox, not the provider.
- Re-login if the stored token has meanwhile expired past recovery.
Defensive patterns
Strategy: try-catch
Try / catch
td, err := auth.RefreshTokens(ctx, rt)
if err != nil && strings.Contains(err.Error(), "failed to parse refresh response") {
// 200 + non-JSON on refresh: suspect middleware rewriting responses
log.Errorf("non-JSON refresh response: %v", err)
} Prevention
- Exclude auth domains from MITM proxies.
- Log raw bodies at debug level when integrating in restricted networks.
When it happens
Trigger: Proxy/portal replacing the refresh response with HTML while keeping 200; truncated body from a buffering middlebox; provider incident serving a malformed payload.
Common situations: Background refresh through corporate MITM infrastructure; captive portals on servers that roamed networks; rare upstream content glitches.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to parse token response: %w
- token refresh request failed: %w
- failed to parse response JSON: %w
- token exchange request failed: %w
- failed to create refresh request: %w
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/7fa8b58a46524500.
Report an issue: GitHub.