charmbracelet/crush · error

failed to execute search: %w

Error message

failed to execute search: %w

What it means

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.

Source

Thrown at internal/agent/tools/search.go:86

var ddgLiteEndpoint = "https://lite.duckduckgo.com/lite/?q="

func searchDuckDuckGo(ctx context.Context, client *http.Client, query string, maxResults int) ([]SearchResult, error) {
	if maxResults <= 0 {
		maxResults = 10
	}

	searchURL := ddgLiteEndpoint + url.QueryEscape(query)

	req, err := http.NewRequestWithContext(ctx, "GET", searchURL, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to create request: %w", err)
	}

	setRandomizedHeaders(req)

	resp, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("failed to execute search: %w", err)
	}
	defer resp.Body.Close()

	// A 202 from DuckDuckGo is the anomaly-challenge interstitial, not a
	// result page; report throttling rather than parsing it into an
	// empty result set.
	if resp.StatusCode == http.StatusAccepted {
		return nil, errSearchRateLimited
	}
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("search failed with status code: %d", resp.StatusCode)
	}

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("failed to read response: %w", err)
	}

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Read the wrapped error to distinguish DNS vs connect vs timeout and fix that layer
  2. Configure HTTPS_PROXY/HTTP_PROXY if outbound traffic needs a proxy
  3. Verify DNS and outbound HTTPS (curl -v https://duckduckgo.com/lite) from the same host
  4. Retry on transient errors; increase client timeout if it fires under load

Example fix

// before
client := &http.Client{} // default, no proxy/timeout tuning
// after
client := &http.Client{
    Transport: &http.Transport{Proxy: http.ProxyFromEnvironment},
    Timeout: 30 * time.Second,
}
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight connectivity check
req, _ := http.NewRequestWithContext(ctx, "HEAD", "https://duckduckgo.com", nil)
if _, err := http.DefaultClient.Do(req); err != nil {
    return fmt.Errorf("no outbound connectivity: %w", err)
}

Try / catch

var netErr net.Error
if errors.As(err, &netErr) && netErr.Timeout() {
    // exponential backoff then retry
}
var dnsErr *net.DNSError
if errors.As(err, &dnsErr) {
    // check DNS / proxy configuration
}

Prevention

When it happens

Trigger: client.Do(req) returns an error: no network, DNS failure, connection refused/timeout, TLS interception, or the http.Client's timeout exceeded.

Common situations: 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.

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/db3a50a1d212a6ae. Report an issue: GitHub.