vxcontrol/pentagi · error · FatalError
duckduckgo search failed: %w
Error message
duckduckgo search failed: %w
What it means
The DuckDuckGo searcher wraps any failure from its internal search() into a Fatal-classified error (`searchers.Fatal`). Per the searchers contract, Fatal means the orchestrator should NOT retry this engine and should move to the next engine in the fallbackStrategy chain. DuckDuckGo already retries transient failures internally, so anything surfacing here is considered terminal for this engine.
Source
Thrown at backend/pkg/tools/searchers/duckduckgo.go:126
observation.Event(
langfuse.WithEventName("search engine error"),
langfuse.WithEventInput(req.Query),
langfuse.WithEventStatus(err.Error()),
langfuse.WithEventLevel(langfuse.ObservationLevelWarning),
langfuse.WithEventMetadata(langfuse.Metadata{
"engine": "duckduckgo",
"query": req.Query,
"max_results": numResults,
"region": d.region(),
"error": err.Error(),
}),
)
obs.LogErrorOrCancel(logger, err, "failed to search in DuckDuckGo")
// DuckDuckGo already retries transient failures internally (see search);
// by the time an error surfaces here, moving to the next engine is the
// right call rather than burning another round-trip on the same one.
return "", Fatal(fmt.Errorf("duckduckgo search failed: %w", err))
}
return result, nil
}
// search performs a web search using DuckDuckGo
func (d *duckduckgo) search(ctx context.Context, query string, maxResults int) (string, error) {
// Build form data for POST request
formData := d.buildFormData(query)
// Create HTTP client with proper configuration
client, err := system.GetHTTPClient(d.cfg)
if err != nil {
return "", fmt.Errorf("failed to create http client: %w", err)
}
client.Timeout = duckduckgoTimeout
View on GitHub (pinned to ea665308ba)
Solutions
- Inspect the wrapped cause: if it's a network/status error, check egress connectivity and proxy settings (HTTP_PROXY/HTTPS_PROXY, cfg proxy config) for the container.
- If it's a parse error, DuckDuckGo likely changed its HTML; update the selectors in parseHTMLStructured/parseHTMLRegex.
- Verify other engines in the web_search fallback chain are configured so orchestration continues despite this Fatal error.
- Reduce request volume or rotate egress IPs if you're seeing repeated 403s (rate-limit/bot detection).
Defensive patterns
Strategy: fallback
Validate before calling
// before calling web_search, check the engine is reachable
resp, err := http.Head("https://duckduckgo.com")
if err != nil || resp.StatusCode >= 500 {
// expect the duckduckgo searcher to fail; ensure other engines configured
} Type guard
var fatal searchers.FatalError
if errors.As(err, &fatal) {
// do not retry this engine; orchestrator moves to next engine
} Try / catch
result, err := webSearch.Handle(ctx, req)
if err != nil {
if searchers.IsFatal(err) {
log.Warn("duckduckgo failed terminally; falling back configured engines")
}
return err // orchestrator already applied fallback chain
} Prevention
- Always configure at least one alternate engine in the web_search fallback chain
- Monitor engine error rates per engine to detect DuckDuckGo blocks early
- Keep request volume within DuckDuckGo's tolerance; add jitter between queries
- Verify container egress (DNS, proxy) during deployment health checks
When it happens
Trigger: Any error returned by d.search() after internal retries: HTTP client construction failure, request-build failure, transport errors after duckduckgoMaxRetries attempts, non-200 status after retries, body-read error, or HTML-parse error.
Common situations: DuckDuckGo rate-limiting or blocking the host (anomaly 403/202 responses); corporate egress proxy blocking duckduckgo.com; TLS interception breaking requests; DuckDuckGo changing HTML layout so parsing yields no results path-related errors; no internet/DNS failure in the container.
Related errors
- failed to execute search after %d attempts: %w
- unexpected status code: %d
- there are temporarily offline for maintenance. please try ag
- failed to generate subtasks for task %d: %w
- knowledge: embed query: %w
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/30ba18622135a2d2.
Report an issue: GitHub.