{"record":{"id":"db3a50a1d212a6ae","repo":"charmbracelet/crush","slug":"failed-to-execute-search-w","errorCode":null,"errorMessage":"failed to execute search: %w","messagePattern":"failed to execute search: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/agent/tools/search.go","lineNumber":86,"sourceCode":"var ddgLiteEndpoint = \"https://lite.duckduckgo.com/lite/?q=\"\n\nfunc searchDuckDuckGo(ctx context.Context, client *http.Client, query string, maxResults int) ([]SearchResult, error) {\n\tif maxResults <= 0 {\n\t\tmaxResults = 10\n\t}\n\n\tsearchURL := ddgLiteEndpoint + url.QueryEscape(query)\n\n\treq, err := http.NewRequestWithContext(ctx, \"GET\", searchURL, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create request: %w\", err)\n\t}\n\n\tsetRandomizedHeaders(req)\n\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to execute search: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\n\t// A 202 from DuckDuckGo is the anomaly-challenge interstitial, not a\n\t// result page; report throttling rather than parsing it into an\n\t// empty result set.\n\tif resp.StatusCode == http.StatusAccepted {\n\t\treturn nil, errSearchRateLimited\n\t}\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"search failed with status code: %d\", resp.StatusCode)\n\t}\n\n\tbody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to read response: %w\", err)\n\t}\n","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/agent/tools/search.go#L68-L104","documentation":"The HTTP request to DuckDuckGo's lite endpoint failed at transport level (client.Do error), wrapped here. This is a network failure — DNS resolution, TCP connect, TLS, timeout, or proxy error — not a bad response. The deferred body close is never reached since no response exists.","triggerScenarios":"client.Do(req) returns an error: no network, DNS failure, connection refused/timeout, TLS interception, or the http.Client's timeout exceeded.","commonSituations":"Running in an air-gapped/behind-firewall environment; corporate proxy not configured (missing HTTPS_PROXY); DNS blocked for duckduckgo.com; transient network outage; client timeout too small for slow links.","solutions":["Read the wrapped error to distinguish DNS vs connect vs timeout and fix that layer","Configure HTTPS_PROXY/HTTP_PROXY if outbound traffic needs a proxy","Verify DNS and outbound HTTPS (curl -v https://duckduckgo.com/lite) from the same host","Retry on transient errors; increase client timeout if it fires under load"],"exampleFix":"// before\nclient := &http.Client{} // default, no proxy/timeout tuning\n// after\nclient := &http.Client{\n    Transport: &http.Transport{Proxy: http.ProxyFromEnvironment},\n    Timeout: 30 * time.Second,\n}","handlingStrategy":"retry","validationCode":"// pre-flight connectivity check\nreq, _ := http.NewRequestWithContext(ctx, \"HEAD\", \"https://duckduckgo.com\", nil)\nif _, err := http.DefaultClient.Do(req); err != nil {\n    return fmt.Errorf(\"no outbound connectivity: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"var netErr net.Error\nif errors.As(err, &netErr) && netErr.Timeout() {\n    // exponential backoff then retry\n}\nvar dnsErr *net.DNSError\nif errors.As(err, &dnsErr) {\n    // check DNS / proxy configuration\n}","preventionTips":["Configure HTTP(S)_PROXY in sandboxed/corporate environments","Set a sane client timeout (e.g. 30s)","Distinguish timeout vs DNS vs connect errors via errors.As","Cache results to reduce dependence on the network"],"tags":["network","http","search"],"backgroundTag":"http-request-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}