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
- Retry the usage query with backoff — transient body truncation usually resolves itself
- Check network path: curl -v the usage endpoint from the same host and watch for truncation
- If it times out consistently, the 10s client timeout is too tight for your latency — report/patch it rather than hammering retries
- 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
- Wrap usage fetches in bounded retry with backoff
- Poll usage sparingly (minutes, not seconds) so flaky reads are rare
- Keep the client on a stable network path free of body-truncating proxies
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
- API error %d: %s
- after %d retries: %w
- failed to get WeCom QR code: %w
- unexpected status %s
- request failed: %w
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/bcb821fc1055b8f9.
Report an issue: GitHub.