charmbracelet/crush · error
failed to make request: %w
Error message
failed to make request: %w
What it means
FetchCredits wraps errors from http.Client.Do when executing the GET <BaseURL>/v1/credits request. This covers DNS failures, connection refused/reset, TLS errors, and the client's 10-second timeout. The HTTP call never completed, so no status code exists.
Source
Thrown at internal/agent/hyper/provider.go:94
balance := int(lastKnownBalance.Load())
return &balance, nil
}
req, err := http.NewRequestWithContext(
ctx,
http.MethodGet,
BaseURL()+"/v1/credits",
nil,
)
if err != nil {
return nil, fmt.Errorf("could not create request: %w", err)
}
req.Header.Set("Authorization", "Bearer "+apiKey)
client := &http.Client{Timeout: 10 * time.Second}
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("failed to make request: %w", err)
}
defer resp.Body.Close() //nolint:errcheck
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
}
// Teams with hypercredit display disabled get a balance_usd field
// instead of balance, and no balance is shown for them at all.
var result struct {
Balance *int `json:"balance"`
}
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return nil, fmt.Errorf("failed to decode response: %w", err)
}
return result.Balance, nil
}View on GitHub (pinned to 7944b8e522)
Solutions
- Check basic reachability: `curl -v $HYPER_URL/v1/credits` (or https://hyper.charm.land/v1/credits) to see the underlying network error.
- If self-hosting via HYPER_URL, verify the proxy is up and listening on the expected port.
- Check proxy environment (HTTP_PROXY/HTTPS_PROXY) and VPN/firewall rules that may block the host.
- For timeouts, retry the call; FetchCredits has no built-in retry and the client timeout is fixed at 10 seconds.
- Respect ctx cancellation: if the caller canceled, fix the caller's timeout/deadline instead of retrying.
Example fix
// before
balance, err := hyper.FetchCredits(ctx, apiKey)
if err != nil { return err } // fails on transient network blips
// after
var balance *int
var err error
for attempt := 0; attempt < 3; attempt++ {
balance, err = hyper.FetchCredits(ctx, apiKey)
if err == nil || ctx.Err() != nil || !errors.Is(err, context.DeadlineExceeded) && !isNetError(err) {
break
}
time.Sleep(time.Duration(attempt+1) * 500 * time.Second / 1000)
} Defensive patterns
Strategy: retry
Validate before calling
conn, err := net.DialTimeout("tcp", host(hyper.BaseURL())+":443", 3*time.Second)
if err != nil {
return fmt.Errorf("hyper endpoint unreachable: %w", err)
}
conn.Close() Type guard
func isNetworkError(err error) bool {
var ne net.Error
if errors.As(err, &ne) { return true }
var oe *net.OpError
return errors.As(err, &oe) || errors.Is(err, context.DeadlineExceeded) || errors.Is(err, syscall.ECONNREFUSED)
} Try / catch
var balance *int
err := retryDo(3, 500*time.Millisecond, func() error {
var e error
balance, e = hyper.FetchCredits(ctx, apiKey)
if e != nil && isNetworkError(e) {
return e // retryable
}
return stop(e) // fatal
}) Prevention
- Wrap FetchCredits in bounded exponential-backoff retry for transient net/timeout errors only.
- Monitor reachability of hyper.charm.land (or your HYPER_URL host) in health checks.
- Document that the internal client timeout is fixed at 10s; keep caller deadlines comfortably above it.
- Verify VPN/proxy rules allow the host in corporate environments.
When it happens
Trigger: Network is down or DNS cannot resolve hyper.charm.land (or the HYPER_URL host); the server is unreachable/firewalled; TLS handshake fails (bad proxy, clock skew); the 10s client Timeout elapses; or ctx is canceled mid-request.
Common situations: Corporate proxy/VPN blocks hyper.charm.land; offline development; self-hosted HYPER_URL proxy not running (connection refused); slow networks tripping the 10-second timeout.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- failed to get LSP diagnostics: %w
- failed to get LSPs: %w
- failed to get MCP states: %w
- failed to get MCP pending auth: %w
- timeout waiting for agent: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/0fca68248312e6df.
Report an issue: GitHub.