charmbracelet/crush · error
failed to download from URL: %w
Error message
failed to download from URL: %w
What it means
The HTTP client's Do call returned an error while attempting the GET request — the request never completed with an HTTP response. The error is wrapped with the job context so callers see the network-level cause (DNS, TLS, timeout, connection refused).
Source
Thrown at internal/agent/tools/download.go:129
maxTimeout := 600 // 10 minutes
if params.Timeout > maxTimeout {
params.Timeout = maxTimeout
}
var cancel context.CancelFunc
requestCtx, cancel = context.WithTimeout(ctx, time.Duration(params.Timeout)*time.Second)
defer cancel()
}
req, err := http.NewRequestWithContext(requestCtx, "GET", params.URL, nil)
if err != nil {
return fantasy.ToolResponse{}, fmt.Errorf("failed to create request: %w", err)
}
req.Header.Set("User-Agent", "crush/1.0")
resp, err := client.Do(req)
if err != nil {
return fantasy.ToolResponse{}, fmt.Errorf("failed to download from URL: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fantasy.NewTextErrorResponse(fmt.Sprintf("Request failed with status code: %d", resp.StatusCode)), nil
}
// Create parent directories if they don't exist
if err := os.MkdirAll(filepath.Dir(filePath), 0o755); err != nil {
return fantasy.ToolResponse{}, fmt.Errorf("failed to create parent directories: %w", err)
}
// Create the output file
outFile, err := os.Create(filePath)
if err != nil {
return fantasy.ToolResponse{}, fmt.Errorf("failed to create output file: %w", err)
}
defer outFile.Close()View on GitHub (pinned to 7944b8e522)
Solutions
- Check the wrapped error for cause: context deadline exceeded means increase params.Timeout
- Verify network connectivity and DNS resolution for the host (curl the URL manually)
- If TLS is the issue, check certificate validity (don't disable verification)
- Retry transient failures or use a mirror URL
Example fix
// before tool call with timeout: 5 (seconds) for a 2GB file // after tool call with timeout: 600 (seconds)
Defensive patterns
Strategy: retry
Validate before calling
// cheap pre-check before the tool call
conn, err := net.DialTimeout("tcp", host+":443", 5*time.Second)
if err != nil { return fmt.Errorf("host unreachable: %v", err) }
conn.Close() Try / catch
if err != nil {
if errors.Is(err, context.DeadlineExceeded) {
return fmt.Errorf("download timed out; raise timeout (max 600s): %w", err)
}
var netErr net.Error
if errors.As(err, &netErr) && netErr.Timeout() {
// retry with backoff
}
return fmt.Errorf("download failed: %w", err)
} Prevention
- Set a generous timeout parameter (up to 600s) for large files
- Verify connectivity/DNS before downloading (curl -I the URL)
- Check proxy/TLS configuration in restricted networks
- Retry transient network errors with backoff
When it happens
Trigger: DNS resolution failure, connection refused/timeout, TLS handshake error, or the request context (params.Timeout, max 600s; client default 5 min) expired during the request.
Common situations: Target host unreachable or offline; corporate proxy/firewall blocking outbound HTTPS; invalid or expired TLS certificates; downloads exceeding the configured timeout on slow links; no network access in sandboxed environments.
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 fetch URL: %w
- failed to fetch URL: %w
- failed to fetch URL: %w
- failed to read response body: %w
- failed to make request: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/c8958d72b0ce11fa.
Report an issue: GitHub.