router-for-me/CLIProxyAPI · error
read Claude OAuth %s response: %w
Error message
read Claude OAuth %s response: %w
What it means
Returned by ClaudeAuth.fetchOAuthControlPlaneJSON when reading the OAuth response body fails, wrapping the error from readClaudeOAuthResponseBody. That helper goes beyond io.ReadAll: because the request advertises Accept-Encoding: gzip, compress, deflate, br, it manually decodes Content-Encoding layers (gzip via compress/gzip, deflate via zlib with flate fallback, br via brotli, compress via lzw). So this error is either a truncated body (unexpected EOF) or a failed decode of a declared content encoding (e.g. corrupt gzip stream, or an encoding the switch does not support).
Source
Thrown at internal/auth/claude/anthropic_auth.go:252
if errRequest != nil {
return nil, fmt.Errorf("create Claude OAuth %s request: %w", label, errRequest)
}
applyClaudeOAuthAxiosHeaders(req)
req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("Cache-Control", "no-cache")
resp, errDo := o.httpClient.Do(req)
if errDo != nil {
return nil, fmt.Errorf("fetch Claude OAuth %s: %w", label, errDo)
}
defer func() {
if errClose := resp.Body.Close(); errClose != nil {
log.Errorf("failed to close Claude OAuth %s response body: %v", label, errClose)
}
}()
body, errRead := readClaudeOAuthResponseBody(resp)
if errRead != nil {
return nil, fmt.Errorf("read Claude OAuth %s response: %w", label, errRead)
}
if resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusMultipleChoices {
return nil, fmt.Errorf("fetch Claude OAuth %s failed with status %d", label, resp.StatusCode)
}
return body, nil
}
// FetchOAuthProfile retrieves the account identity associated with an OAuth access token.
func (o *ClaudeAuth) FetchOAuthProfile(ctx context.Context, accessToken string) (*OAuthProfile, error) {
body, errFetch := o.fetchOAuthControlPlaneJSON(ctx, ProfileURL, accessToken, "profile")
if errFetch != nil {
return nil, errFetch
}
var profile OAuthProfile
if errUnmarshal := json.Unmarshal(body, &profile); errUnmarshal != nil {
return nil, fmt.Errorf("parse Claude OAuth profile response: %w", errUnmarshal)
}
if strings.TrimSpace(profile.Account.UUID) == "" {View on GitHub (pinned to 78f0c4079e)
Solutions
- Read the wrapped message: 'unexpected EOF' → network truncation, retry; 'unsupported content encoding' or 'decode ... gzip/brotli' → intermediary re-encoding, inspect the proxy chain
- Bypass or disable response re-compression on the intercepting middlebox
- Retry the auth flow; single truncated responses are transient
Defensive patterns
Strategy: retry
Try / catch
profile, err := auth.FetchOAuthProfile(ctx, token)
if err != nil {
msg := err.Error()
if strings.Contains(msg, "unexpected EOF") || strings.Contains(msg, "decode Claude OAuth") {
// truncated or undecodable compressed body: retry once, then inspect proxy chain
time.Sleep(time.Second)
profile, err = auth.FetchOAuthProfile(ctx, token)
}
if err != nil { return err }
} Prevention
- Disable response re-compression on SSL-inspecting middleboxes in front of the proxy
- Treat decode failures on gzip/br bodies as a sign an intermediary is rewriting responses
When it happens
Trigger: Connection reset mid-body; server sending a Content-Encoding the decoder cannot handle (custom or mislabeled encoding yields 'unsupported content encoding'); corrupt compressed payload from an intermediary that re-encodes the body but keeps the original Content-Encoding header.
Common situations: Antivirus/SSL-inspection appliances recompressing responses inconsistently; flaky networks truncating compressed streams; rare server-side encoding bugs. If the message contains 'unsupported content encoding', an intermediary is re-writing headers.
Related errors
- fetch Claude OAuth %s: %w
- decode Claude OAuth gzip response: %w
- decode Claude OAuth %s response: %w
- claude oauth tls: dial upstream: %w
- failed to read token response: %w
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/0565b4604e410f2a.
Report an issue: GitHub.