vxcontrol/pentagi · error
failed to execute search after %d attempts: %w
Error message
failed to execute search after %d attempts: %w
What it means
The POST to DuckDuckGo failed on every one of duckduckgoMaxRetries attempts; on the final attempt the last transport error is wrapped and returned. Transient failures between attempts sleep 1s (or return ctx.Err() if the context is cancelled). Upstream, Handle classifies this as Fatal so the orchestrator falls back to the next engine.
Source
Thrown at backend/pkg/tools/searchers/duckduckgo.go:162
// Execute request with retry logic
var response *searchResponse
for attempt := 0; attempt < duckduckgoMaxRetries; attempt++ {
req, err := http.NewRequestWithContext(ctx, "POST", duckduckgoSearchURL, strings.NewReader(formData))
if err != nil {
return "", fmt.Errorf("failed to create search request: %w", err)
}
// Add necessary headers for POST request
req.Header.Set("User-Agent", duckduckgoUserAgent)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
req.Header.Set("Accept-Language", "en-US,en;q=0.9")
resp, err := client.Do(req)
if err != nil {
if attempt == duckduckgoMaxRetries-1 {
return "", fmt.Errorf("failed to execute search after %d attempts: %w", duckduckgoMaxRetries, err)
}
select {
case <-ctx.Done():
return "", ctx.Err()
case <-time.After(time.Second):
}
continue
}
if resp.StatusCode != http.StatusOK {
resp.Body.Close()
if attempt == duckduckgoMaxRetries-1 {
return "", fmt.Errorf("unexpected status code: %d", resp.StatusCode)
}
select {
case <-ctx.Done():
return "", ctx.Err()
case <-time.After(time.Second):View on GitHub (pinned to ea665308ba)
Solutions
- Read the wrapped cause (e.g. 'dial tcp ... i/o timeout', 'no such host', 'connection refused') and fix the underlying network/DNS/proxy issue.
- Confirm egress from the container: `docker exec <c> wget -qO- https://duckduckgo.com` to isolate host vs container networking.
- Increase duckduckgoTimeout or retry backoff if failures are borderline timeouts on slow networks.
- Ensure a fallback engine (Google, Tavily, etc.) is configured so web_search still returns results.
Defensive patterns
Strategy: retry
Validate before calling
// check egress before issuing searches
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
if err := checkConnectivity(ctx, "https://duckduckgo.com"); err != nil {
// engine unavailable; skip to fallback engine
} Type guard
var netErr net.Error
if errors.As(err, &netErr) && netErr.Timeout() {
// transient timeout; safe to retry with backoff
} Try / catch
result, err := d.search(ctx, query, numResults)
if err != nil {
if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) {
return "", err // don't wrap cancellation
}
return "", Fatal(fmt.Errorf("duckduckgo search failed: %w", err))
} Prevention
- Set a sane client timeout (duckduckgoTimeout) matched to worst-case network latency
- Use exponential backoff between retries instead of fixed 1s
- Verify container DNS and proxy settings during deployment
- Monitor wrapped cause strings to distinguish DNS vs connect vs TLS failures
When it happens
Trigger: client.Do returns an error on all retries: DNS resolution failure, TCP connect refused/timeout, TLS handshake failure, context deadline exceeded while the request is in flight on the last attempt, or proxy unreachable.
Common situations: Container has no internet or broken DNS; corporate firewall blocks duckduckgo.com; DuckDuckGo rate-limits/blocks your IP leading to connection resets; http client timeout (duckduckgoTimeout) too short on a slow link; proxy misconfigured.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
Related errors
- failed to do request: %v
- image download stream processing failed: %w
- duckduckgo search failed: %w
- failed to read response body: %w
- failed to send request: %w
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/2efa37377e5df34a.
Report an issue: GitHub.