sipeed/picoclaw · error

reading usage response: %w

Error message

reading usage response: %w

What it means

io.ReadAll(resp.Body) failed at pkg/auth/anthropic_usage.go:45 while reading the Anthropic usage endpoint's response body. The HTTP request itself succeeded (client.Do returned), so this is a mid-body transport failure — the connection broke or the 10-second http.Client timeout fired while streaming the body. Status code handling never runs in this case.

Source

Thrown at pkg/auth/anthropic_usage.go:45

func FetchAnthropicUsage(token string) (*AnthropicUsage, error) {
	req, err := http.NewRequest("GET", anthropicUsageURL, nil)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Authorization", "Bearer "+token)
	req.Header.Set("Anthropic-Version", anthropicAPIVersion)
	req.Header.Set("Anthropic-Beta", anthropicBetaHeader)

	client := &http.Client{Timeout: 10 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("reading usage response: %w", err)
	}

	if resp.StatusCode != http.StatusOK {
		if resp.StatusCode == http.StatusForbidden {
			return nil, fmt.Errorf("insufficient scope: usage endpoint requires oauth scope")
		}
		return nil, fmt.Errorf("usage request failed (%d): %s", resp.StatusCode, string(body))
	}

	var result struct {
		FiveHour struct {
			Utilization float64 `json:"utilization"`
		} `json:"five_hour"`
		SevenDay struct {
			Utilization float64 `json:"utilization"`
		} `json:"seven_day"`
	}
	if err := json.Unmarshal(body, &result); err != nil {

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Retry the usage query with backoff — transient body truncation usually resolves itself
  2. Check network path: curl -v the usage endpoint from the same host and watch for truncation
  3. If it times out consistently, the 10s client timeout is too tight for your latency — report/patch it rather than hammering retries
  4. Disable or bypass HTTP(S)_PROXY for api.anthropic.com if a proxy is mangling bodies

Example fix

// before: single fetch of usage
usage, err := auth.FetchAnthropicUsage(ctx, token)

// after: bounded retry for transport-level body failures
var usage *auth.AnthropicUsage
err := retryN(3, 500*time.Millisecond, func() error {
    u, e := auth.FetchAnthropicUsage(ctx, token)
    if u != nil { usage = u }
    return e
})
Defensive patterns

Strategy: retry

Try / catch

var usage *auth.AnthropicUsage
err := retryN(3, time.Second, func() error {
    u, e := fetchUsage(ctx, token)
    if e != nil && strings.Contains(e.Error(), "reading usage response") {
        return e // transport-level body failure: safe to retry
    }
    if u != nil { usage = u }
    return retryStop{e}
})

Prevention

When it happens

Trigger: Connection reset between headers and body completion; slow endpoint where the fixed 10s client timeout (client := &http.Client{Timeout: 10 * time.Second}) fires during body read; intermediary proxy truncating the response; TLS renegotiation dropping the stream.

Common situations: Mobile/high-latency networks; corporate proxies that buffer headers then cut long bodies; Anthropic API slowness during incidents; captive portals injecting truncated responses.

Related errors


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/bcb821fc1055b8f9. Report an issue: GitHub.