charmbracelet/crush · error

failed to make request

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.

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.

Appendix: 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)