router-for-me/CLIProxyAPI · error
failed to read refresh response: %w
Error message
failed to read refresh response: %w
What it means
io.ReadAll failed while reading the token refresh response body — the status line arrived but the body stream aborted (reset, truncation, or context cancellation during read). Functionally identical to error 203 but on the refresh path; it is a transport-level truncation, not a provider rejection.
Source
Thrown at internal/auth/codex/openai_auth.go:241
return nil, fmt.Errorf("failed to create refresh request: %w", errReq)
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Accept", "application/json")
resp, errDo := o.httpClient.Do(req)
if errDo != nil {
return nil, fmt.Errorf("token refresh request failed: %w", errDo)
}
defer func() {
if errClose := resp.Body.Close(); errClose != nil {
log.Errorf("token refresh response body close error: %v", errClose)
}
}()
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)
}
View on GitHub (pinned to 78f0c4079e)
Solutions
- Let the retry loop handle it — single truncations clear on retry.
- If recurring, capture the wrapped error to identify who truncates (EOF vs reset vs canceled).
- Exclude the auth host from problematic proxies/VPNs.
- Ensure the refresh context deadline comfortably exceeds the full round trip.
Defensive patterns
Strategy: retry
Try / catch
td, err := auth.RefreshTokensWithRetry(ctx, rt, 3)
if err != nil && strings.Contains(err.Error(), "failed to read refresh response") {
// truncation: transient; next scheduled refresh will retry
} Prevention
- Rely on the built-in backoff retry loop for background refreshes.
- Investigate only after repeated truncations — then look at proxies.
When it happens
Trigger: Connection reset after response headers during background refresh; context canceled mid-body; intermediary truncating the streamed response; keep-alive races with proxies.
Common situations: Background refresh on flaky networks; proxy idle-timeout closing the stream; shutdown races canceling the refresh context mid-read.
Related errors
- failed to read token response: %w
- token refresh request failed: %w
- token refresh failed after %d attempts: %w
- read response: %w
- read Claude OAuth %s response: %w
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/fb2481e4e73d2be2.
Report an issue: GitHub.