Tencent/WeKnora · error
duckduckgo API search failed
Error message
duckduckgo API search failed: %w
What it means
This is the DuckDuckGo Instant Answer API fallback failure: the HTML search failed and searchAPI returned an error, so Search wraps the API error as "duckduckgo API search failed". Both the HTML scrape and the API fallback failed.
Solutions
- Inspect the wrapped apiErr for the underlying network/HTTP cause.
- Verify outbound HTTPS connectivity to duckduckgo.com and api.duckduckgo.com.
- Implement exponential backoff and retry for transient network failures.
- Configure an alternate provider (e.g. Bing/Brave/Serper) as a final fallback.
Defensive patterns
Strategy: fallback
Validate before calling
conn, err := net.DialTimeout("tcp", "duckduckgo.com:443", 3*time.Second)
if err != nil {
return errors.New("no connectivity to duckduckgo; check network")
}
conn.Close() Type guard
func isDDGAPIFailure(err error) bool {
return err != nil && strings.Contains(err.Error(), "duckduckgo API search failed")
} Try / catch
results, err := ddg.Search(ctx, query, 10, false)
if err != nil {
if isDDGAPIFailure(err) || isDDGHTMLFailure(err) {
results, err = altProvider.Search(ctx, query, 10, false)
}
} Prevention
- Check outbound network/DNS in the deployment environment (CI containers often block egress).
- Set explicit HTTP client timeouts so failures surface fast.
- Maintain a provider priority list with automatic failover.
When it happens
Trigger: searchHTML returned an error, and searchAPI also returned an error (apiErr != nil), so control reaches the second fmt.Errorf in Search.
Common situations: Total loss of network connectivity; DNS failures; the Instant Answer API returning 403/rate limits; queries for which the API errors instead of returning empty results.
Related errors
- bing API returned status
- duckduckgo HTML search failed
- failed to perform request
- keenable API returned status
- create sandbox binding
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/b602785f3481e2e3.
Report an issue: GitHub.
Appendix: source
Thrown at internal/infrastructure/web_search/duckduckgo.go:63
includeDate bool,
) ([]*types.WebSearchResult, error) {
if maxResults <= 0 {
maxResults = 5
}
// Try HTML scraping first (more reliable for general results)
htmlResults, err := p.searchHTML(ctx, query, maxResults)
if err == nil && len(htmlResults) > 0 {
return htmlResults, nil
}
// Fallback to Instant Answer API
apiResults, apiErr := p.searchAPI(ctx, query, maxResults)
if apiErr == nil && len(apiResults) > 0 {
return apiResults, nil
}
if err != nil {
return nil, fmt.Errorf("duckduckgo HTML search failed: %w", err)
}
return nil, fmt.Errorf("duckduckgo API search failed: %w", apiErr)
}
// searchHTML performs a web search using DuckDuckGo HTML endpoint
func (p *DuckDuckGoProvider) searchHTML(
ctx context.Context,
query string,
maxResults int,
) ([]*types.WebSearchResult, error) {
baseURL := "https://html.duckduckgo.com/html/"
params := url.Values{}
params.Set("q", query)
params.Set("kl", "cn-zh")
reqURL := baseURL + "?" + params.Encode()
req, err := http.NewRequestWithContext(ctx, "GET", reqURL, nil)
if err != nil {
return nil, fmt.Errorf("failed to create request: %w", err)
}View on GitHub (pinned to 988cbb0330)