charmbracelet/crush · error
failed to create request: %w
Error message
failed to create request: %w
What it means
searchDuckDuckGo builds an outbound http.NewRequestWithContext GET to the DuckDuckGo lite endpoint; if http.NewRequestWithContext itself errors (it only fails on malformed URLs or an invalid context), this wrapped error is returned before any network I/O. In practice this almost always means the escaped query produced an unparsable URL.
Source
Thrown at internal/agent/tools/search.go:79
"anomaly-modal",
"/anomaly.js",
"Unfortunately, bots use DuckDuckGo too",
}
// ddgLiteEndpoint is a package var so tests can point the search at a
// local httptest server.
var ddgLiteEndpoint = "https://lite.duckduckgo.com/lite/?q="
func searchDuckDuckGo(ctx context.Context, client *http.Client, query string, maxResults int) ([]SearchResult, error) {
if maxResults <= 0 {
maxResults = 10
}
searchURL := ddgLiteEndpoint + url.QueryEscape(query)
req, err := http.NewRequestWithContext(ctx, "GET", searchURL, nil)
if err != nil {
return nil, fmt.Errorf("failed to create request: %w", err)
}
setRandomizedHeaders(req)
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("failed to execute search: %w", err)
}
defer resp.Body.Close()
// A 202 from DuckDuckGo is the anomaly-challenge interstitial, not a
// result page; report throttling rather than parsing it into an
// empty result set.
if resp.StatusCode == http.StatusAccepted {
return nil, errSearchRateLimited
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("search failed with status code: %d", resp.StatusCode)View on GitHub (pinned to 7944b8e522)
Solutions
- Sanitize the query: strip control characters/newlines before calling the tool
- Inspect the wrapped error's URL parse message for the offending character
- Verify the search endpoint configuration hasn't been overridden with an invalid URL
- Check ctx cancellation if constructing with a pre-canceled context
Example fix
// before
query = strings.TrimSpace(rawQuery) // may still contain \n or control bytes
// after
query = strings.Map(func(r rune) rune {
if r < 0x20 { return -1 }
return r
}, rawQuery) Defensive patterns
Strategy: validation
Validate before calling
func sanitizeQuery(q string) string {
return strings.Map(func(r rune) rune {
if r < 0x20 || r == 0x7f { return -1 }
return r
}, strings.TrimSpace(q))
}
query = sanitizeQuery(query) Try / catch
var urlErr *url.Error
if err := searchDuckDuckGo(ctx, q); err != nil && errors.As(err, &urlErr) {
// urlErr.Op == "parse": malformed URL — fix the query/endpoint
} Prevention
- Strip control characters from model-provided queries
- Validate the endpoint constant if it is configurable
- Detect pre-canceled contexts before issuing requests
- Unit-test search with adversarial query strings
When it happens
Trigger: http.NewRequestWithContext(ctx, "GET", ddgLiteEndpoint+url.QueryEscape(query), nil) returns an error — typically a control character or malformed URL after escaping, or an already-canceled ctx passed at construction.
Common situations: Query strings containing raw newlines/control bytes forwarded from model output; endpoint constant corrupted by config override; passing a canceled context.
Related errors
- failed to execute search: %w
- failed to download from URL: %w
- failed to create request: %w
- failed to fetch URL: %w
- failed to fetch URL: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/d37e4a689e43dc44.
Report an issue: GitHub.