router-for-me/CLIProxyAPI · error
failed to read token response: %w
Error message
failed to read token response: %w
What it means
io.ReadAll failed while draining the token exchange response body. The server was reached and responded, but the body read aborted — typically because the connection was reset mid-body, the context was canceled during the read, or a proxy closed the stream early. Distinct from a non-200 status: the status line was received but the payload is incomplete.
Source
Thrown at internal/auth/codex/openai_auth.go:134
req, err := http.NewRequestWithContext(ctx, "POST", TokenURL, strings.NewReader(data.Encode()))
if err != nil {
return nil, fmt.Errorf("failed to create token request: %w", err)
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Accept", "application/json")
resp, err := o.httpClient.Do(req)
if err != nil {
return nil, fmt.Errorf("token exchange request failed: %w", err)
}
defer func() {
_ = resp.Body.Close()
}()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read token response: %w", err)
}
// log.Debugf("Token response: %s", string(body))
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("token exchange failed with status %d: %s", resp.StatusCode, string(body))
}
// Parse token response
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 err = json.Unmarshal(body, &tokenResp); err != nil {
return nil, fmt.Errorf("failed to parse token response: %w", err)View on GitHub (pinned to 78f0c4079e)
Solutions
- Retry the login — mid-body resets are overwhelmingly transient.
- If reproducible, capture the wrapped error (unexpected EOF vs context.Canceled) to see who cut the stream.
- Bypass or fix the intermediary (proxy/VPN) suspected of truncating responses.
- Ensure the context deadline covers the full body read, not just the dial.
Defensive patterns
Strategy: retry
Try / catch
tok, err := auth.ExchangeCode(ctx, code)
if err != nil && strings.Contains(err.Error(), "failed to read token response") {
// body truncation: transient; restart the flow rather than replaying the code
log.Warnf("truncated token response: %v", err)
} Prevention
- Prefer stable networks for interactive login.
- Avoid proxies known to buffer/limit response bodies for auth domains.
- Treat any single truncation as transient; two in a row means an intermediary problem.
When it happens
Trigger: Upstream or intermediary closes the connection after headers; context canceled while body is streaming; proxy response buffering limits truncating the body; very rare kernel-level socket errors.
Common situations: Flaky mobile/tethered networks during login; aggressive corporate proxies cutting long responses; racing shutdown signals canceling the request context mid-read.
Related errors
- failed to read refresh response: %w
- token exchange request failed: %w
- token refresh request failed: %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/5088bf19ab6eb379.
Report an issue: GitHub.