vxcontrol/pentagi · error
failed to create search request: %w
Error message
failed to create search request: %w
What it means
http.NewRequestWithContext fails while constructing the POST request to the DuckDuckGo HTML endpoint. In net/http this errors only on an unparseable URL or invalid method/ctx-nil combination, so this wrap is a defensive guard around the constant duckduckgoSearchURL. It aborts the search immediately (no retry) and becomes a Fatal engine failure in Handle.
Source
Thrown at backend/pkg/tools/searchers/duckduckgo.go:150
// 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
// 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):
}View on GitHub (pinned to ea665308ba)
Solutions
- Read the wrapped error: it names the parse problem with the URL; fix the duckduckgoSearchURL constant or its source value.
- Assert the URL parses at startup (url.Parse in an init/test) to fail fast after edits.
- If the URL became configurable, validate it before passing to NewRequestWithContext.
Example fix
// before duckduckgoSearchURL = "https://duckduckgo.com/ html" // after duckduckgoSearchURL = "https://duckduckgo.com/html/"
Defensive patterns
Strategy: validation
Validate before calling
if _, err := url.Parse(duckduckgoSearchURL); err != nil {
panic(fmt.Sprintf("duckduckgoSearchURL invalid: %v", err))
} Try / catch
req, err := http.NewRequestWithContext(ctx, "POST", duckduckgoSearchURL, strings.NewReader(formData))
if err != nil {
return "", fmt.Errorf("failed to create search request: %w", err)
} Prevention
- Keep the endpoint URL a validated package-level constant
- Add an init-time or unit-test assertion that all searcher endpoint URLs parse
- If the URL becomes configurable, validate it in config loading
When it happens
Trigger: Only when the request URL is malformed or the method string is invalid. Since duckduckgoSearchURL and "POST" are compile-time constants, this is practically unreachable unless the URL constant is edited to an invalid value or the code is changed to interpolate a bad URL.
Common situations: A developer edits duckduckgoSearchURL and introduces whitespace/typo; refactoring the URL to come from config with a bad value; nil context misuse after refactor.
Related errors
- bearer scheme must be used
- token can't be empty
- failed to build request: %v
- failed to create request: %w
- failed to create request: %w
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/9c8556819d034846.
Report an issue: GitHub.