Tencent/WeKnora · error
failed to create Exa request: %w
Error message
failed to create Exa request: %w
What it means
Wraps errors from http.NewRequestWithContext when constructing the POST request to the Exa API. Given a constant http.MethodPost and a configured baseURL, failures indicate the configured base URL is not a valid URL or the context is invalid.
Source
Thrown at internal/infrastructure/web_search/exa.go:89
}
if maxResults > maxExaResults {
maxResults = maxExaResults
}
bodyBytes, err := json.Marshal(exaSearchRequest{
Query: query,
NumResults: maxResults,
Contents: exaContents{
Highlights: true,
Text: p.includeText,
},
})
if err != nil {
return nil, fmt.Errorf("failed to marshal Exa request: %w", err)
}
req, err := http.NewRequestWithContext(ctx, http.MethodPost, p.baseURL, bytes.NewReader(bodyBytes))
if err != nil {
return nil, fmt.Errorf("failed to create Exa request: %w", err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("x-api-key", p.apiKey)
logger.Infof(ctx, "[WebSearch][Exa] query=%q maxResults=%d url=%s", query, maxResults, p.baseURL)
resp, err := p.client.Do(req)
if err != nil {
return nil, fmt.Errorf("failed to execute Exa request: %w", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(io.LimitReader(resp.Body, maxExaResponseBytes))
if err != nil {
return nil, fmt.Errorf("failed to read Exa response: %w", err)
}
if resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusMultipleChoices {
logger.Warnf(ctx, "[WebSearch][Exa] API returned status %d: %s", resp.StatusCode, string(body))
return nil, fmt.Errorf("exa API returned status %d: %s", resp.StatusCode, string(body))
}View on GitHub (pinned to 988cbb0330)
Solutions
- Verify p.baseURL is a valid absolute http(s) URL (log it on failure)
- Ensure the context passed to Search is valid and not pre-canceled
- Compare the configured base URL against the official Exa endpoint https://api.exa.ai/search
- Unwrap the %w error for the exact url.Parse failure
Example fix
// before
req, err := http.NewRequestWithContext(ctx, http.MethodPost, p.baseURL, bytes.NewReader(bodyBytes))
// after
u, perr := url.Parse(p.baseURL)
if perr != nil || u.Scheme == "" || u.Host == "" {
return nil, fmt.Errorf("invalid exa baseURL %q: %w", p.baseURL, perr)
}
req, err := http.NewRequestWithContext(ctx, http.MethodPost, p.baseURL, bytes.NewReader(bodyBytes)) Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(cfg.ExaBaseURL)
if err != nil || u.Scheme == "" || u.Host == "" {
return fmt.Errorf("invalid exa base URL %q", cfg.ExaBaseURL)
}
if err := ctx.Err(); err != nil {
return err
} Try / catch
results, err := provider.Search(ctx, query, 10, false)
if err != nil {
if errors.Is(err, context.Canceled) {
return nil, fmt.Errorf("search canceled: %w", err)
}
return nil, err
} Prevention
- Validate the base URL at provider construction, not per-request
- Use the official endpoint https://api.exa.ai/search as the default
- Check context validity before dispatching long search operations
When it happens
Trigger: Calling Search when p.baseURL is malformed (bad config/default override) or ctx passed into Search is already canceled/invalid.
Common situations: A config override set baseURL to a garbage value, missing scheme in a custom endpoint, or an upstream canceled context propagated into Search.
Related errors
- create verification request failed: %w
- create request: %w
- failed to create request: %w
- failed to create request: %w
- failed to create request: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/2485618480906dd4.
Report an issue: GitHub.