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

  1. Read the wrapped message: 'unexpected EOF' → network truncation, retry; 'unsupported content encoding' or 'decode ... gzip/brotli' → intermediary re-encoding, inspect the proxy chain
  2. Bypass or disable response re-compression on the intercepting middlebox
  3. 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

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


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