{"record":{"id":"c8958d72b0ce11fa","repo":"charmbracelet/crush","slug":"failed-to-download-from-url-w","errorCode":null,"errorMessage":"failed to download from URL: %w","messagePattern":"failed to download from URL: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/agent/tools/download.go","lineNumber":129,"sourceCode":"\t\t\t\tmaxTimeout := 600 // 10 minutes\n\t\t\t\tif params.Timeout > maxTimeout {\n\t\t\t\t\tparams.Timeout = maxTimeout\n\t\t\t\t}\n\t\t\t\tvar cancel context.CancelFunc\n\t\t\t\trequestCtx, cancel = context.WithTimeout(ctx, time.Duration(params.Timeout)*time.Second)\n\t\t\t\tdefer cancel()\n\t\t\t}\n\n\t\t\treq, err := http.NewRequestWithContext(requestCtx, \"GET\", params.URL, nil)\n\t\t\tif err != nil {\n\t\t\t\treturn fantasy.ToolResponse{}, fmt.Errorf(\"failed to create request: %w\", err)\n\t\t\t}\n\n\t\t\treq.Header.Set(\"User-Agent\", \"crush/1.0\")\n\n\t\t\tresp, err := client.Do(req)\n\t\t\tif err != nil {\n\t\t\t\treturn fantasy.ToolResponse{}, fmt.Errorf(\"failed to download from URL: %w\", err)\n\t\t\t}\n\t\t\tdefer resp.Body.Close()\n\n\t\t\tif resp.StatusCode != http.StatusOK {\n\t\t\t\treturn fantasy.NewTextErrorResponse(fmt.Sprintf(\"Request failed with status code: %d\", resp.StatusCode)), nil\n\t\t\t}\n\n\t\t\t// Create parent directories if they don't exist\n\t\t\tif err := os.MkdirAll(filepath.Dir(filePath), 0o755); err != nil {\n\t\t\t\treturn fantasy.ToolResponse{}, fmt.Errorf(\"failed to create parent directories: %w\", err)\n\t\t\t}\n\n\t\t\t// Create the output file\n\t\t\toutFile, err := os.Create(filePath)\n\t\t\tif err != nil {\n\t\t\t\treturn fantasy.ToolResponse{}, fmt.Errorf(\"failed to create output file: %w\", err)\n\t\t\t}\n\t\t\tdefer outFile.Close()","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/agent/tools/download.go#L111-L147","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\ntool call with timeout: 5 (seconds) for a 2GB file\n// after\ntool call with timeout: 600 (seconds)","handlingStrategy":"retry","validationCode":"// cheap pre-check before the tool call\nconn, err := net.DialTimeout(\"tcp\", host+\":443\", 5*time.Second)\nif err != nil { return fmt.Errorf(\"host unreachable: %v\", err) }\nconn.Close()","typeGuard":null,"tryCatchPattern":"if err != nil {\n    if errors.Is(err, context.DeadlineExceeded) {\n        return fmt.Errorf(\"download timed out; raise timeout (max 600s): %w\", err)\n    }\n    var netErr net.Error\n    if errors.As(err, &netErr) && netErr.Timeout() {\n        // retry with backoff\n    }\n    return fmt.Errorf(\"download failed: %w\", err)\n}","preventionTips":["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"],"tags":["network","http","download","timeout"],"backgroundTag":"http-request-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}