charmbracelet/crush · error

failed to make request: %w

Error message

failed to make request: %w

What it means

This error wraps a network/transport failure from the Hyper API HTTP client in doGet. It is returned when http.Client.Do fails before a response is received — DNS failure, connection refused, timeout (30s), TLS error, or context cancellation. Callers of Get see it via the wrapped error chain.

Source

Thrown at internal/config/hyper.go:161

	var result catwalk.Provider
	req, err := http.NewRequestWithContext(
		ctx,
		http.MethodGet,
		r.baseURL+"/api/v1/provider",
		nil,
	)
	if err != nil {
		return result, fmt.Errorf("could not create request: %w", err)
	}
	xetag.Request(req, etag)
	if apiKey := r.resolveKey(); apiKey != "" {
		req.Header.Set("Authorization", "Bearer "+apiKey)
	}

	client := &http.Client{Timeout: 30 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		return result, fmt.Errorf("failed to make request: %w", err)
	}
	defer resp.Body.Close() //nolint:errcheck

	if resp.StatusCode == http.StatusNotModified {
		return result, catwalk.ErrNotModified
	}

	if resp.StatusCode == http.StatusUnauthorized {
		return result, errUnauthorized
	}

	if resp.StatusCode != http.StatusOK {
		return result, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
	}

	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		return result, fmt.Errorf("failed to decode response: %w", err)
	}

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Verify network connectivity and that the Hyper API host is reachable (curl the endpoint).
  2. Check proxy environment variables (HTTP_PROXY/HTTPS_PROXY) and corporate proxy settings.
  3. Check whether the request is timing out after 30s and address latency or increase tolerance.
  4. Confirm DNS resolves the API host correctly (dig/nslookup).

Example fix

// before: no way to distinguish network failure
resp, err := client.Do(req)
if err != nil {
	return result, fmt.Errorf("failed to make request: %w", err)
}
// after: caller inspects the wrapped error
var netErr net.Error
if errors.As(err, &netErr) && netErr.Timeout() {
	// retry with backoff
}
Defensive patterns

Strategy: retry

Validate before calling

if _, err := net.LookupTimeout("tcp", "api.hyper.example:443", 3*time.Second); err != nil {
	// skip network-dependent init
}

Type guard

var netErr net.Error
isTimeout := errors.As(err, &netErr) && netErr.Timeout()

Try / catch

cfg, err := config.Get()
if err != nil && strings.Contains(err.Error(), "failed to make request") {
	var netErr net.Error
	if errors.As(err, &netErr) && netErr.Timeout() {
		// retry with backoff
	}
}

Prevention

When it happens

Trigger: Calling config.Get (which calls doGet) when the Hyper endpoint is unreachable, the network is down, DNS resolution fails, the request exceeds the 30-second client timeout, or TLS handshake fails.

Common situations: Working offline or behind a corporate proxy that blocks the endpoint; DNS misconfiguration; slow/misbehaving API causing 30s timeout; firewall dropping connections.

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


AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29). Data as JSON: /api/errors/784e36547583692e. Report an issue: GitHub.