Tencent/WeKnora · error
failed to perform request: %w
Error message
failed to perform request: %w
What it means
The HTTP client failed to execute the DuckDuckGo HTML search request in searchHTML (transport-level failure), wrapped as "failed to perform request". No response was received, so this is a connection/TLS/DNS/context problem rather than a bad status.
Source
Thrown at internal/infrastructure/web_search/duckduckgo.go:95
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)
}
req.Header.Set(
"User-Agent",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
)
curlCommand := fmt.Sprintf(
"curl -X GET '%s' -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'",
req.URL.String(),
)
logger.Infof(ctx, "Curl of request: %s", secutils.SanitizeForLog(curlCommand))
resp, err := p.client.Do(req)
if err != nil {
return nil, fmt.Errorf("failed to perform request: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusAccepted {
return nil, fmt.Errorf("duckduckgo HTML returned status %d", resp.StatusCode)
}
doc, err := goquery.NewDocumentFromReader(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to parse HTML: %w", err)
}
results := make([]*types.WebSearchResult, 0, maxResults)
doc.Find(".web-result").Each(func(i int, s *goquery.Selection) {
if len(results) >= maxResults {
return
}
titleNode := s.Find(".result__a")View on GitHub (pinned to 988cbb0330)
Solutions
- Check the wrapped error class: context.DeadlineExceeded -> increase timeout or retry; connection refused -> verify network/proxy.
- Confirm outbound HTTPS to html.duckduckgo.com is allowed from your host.
- Configure an HTTP proxy on p.client if running behind corporate egress.
- Add retry with backoff for transient transport errors.
Defensive patterns
Strategy: retry
Validate before calling
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() // pass ctx into the search call
Type guard
func isTransportErr(err error) bool {
if err == nil { return false }
var ne net.Error
return errors.As(err, &ne) || strings.Contains(err.Error(), "failed to perform request")
} Try / catch
var lastErr error
for attempt := 0; attempt < 3; attempt++ {
results, err := ddg.Search(ctx, query, 10, false)
if err == nil { return results, nil }
lastErr = err
if strings.Contains(err.Error(), "failed to perform request") {
time.Sleep(backoff(attempt)) // transport error: retry
continue
}
break // non-transport: don't retry
} Prevention
- Set sane client timeouts (connect + total) on the HTTP client.
- Verify egress/firewall rules for duckduckgo.com in each environment.
- Use errors.As with net.Error to distinguish timeouts from hard failures.
- Configure proxy settings where corporate egress is required.
When it happens
Trigger: client.Do(req) returns an error: DNS resolution failure, connection refused/timeout, TLS handshake failure, or ctx cancellation mid-request.
Common situations: No internet access or blocked egress (firewall, sandboxed CI); DuckDuckGo refusing datacenter IPs at TLS level; requests without a timeout hanging until the context deadline.
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
- duckduckgo HTML search failed: %w
- duckduckgo API search failed: %w
- failed to execute request: %w
- rerank call failed: %w
- failed to do bulk: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/2f7a4e0ed2451716.
Report an issue: GitHub.