Tencent/WeKnora · error
failed to marshal Exa request: %w
Error message
failed to marshal Exa request: %w
What it means
Wraps errors from json.Marshal when serializing the Exa search request payload (query, result count, contents options). With a plain struct of string/bool/int fields this is nearly impossible at runtime and signals a programming or struct-definition problem rather than an environmental one.
Source
Thrown at internal/infrastructure/web_search/exa.go:85
return nil, fmt.Errorf("query is empty")
}
if maxResults <= 0 {
maxResults = defaultExaResults
}
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)
}View on GitHub (pinned to 988cbb0330)
Solutions
- Review the request struct for unsupported field types or faulty custom MarshalJSON methods
- Revert recent changes to the exaRequest struct
- If truly impossible, treat as an internal invariant bug and alert rather than retry
- Check the unwrapped json.UnsupportedTypeError for the offending field
Example fix
// before
Contents: exaContents{ Channel: make(chan int) }, // unmarshalable field
// after
Contents: exaContents{ Highlights: true, Text: p.includeText }, Defensive patterns
Strategy: validation
Validate before calling
func validateExaRequestFields(r exaRequest) error {
if r.NumResults < 0 {
return errors.New("numResults must be non-negative")
}
return nil // current struct is JSON-safe; marshal errors indicate a struct change
} Try / catch
results, err := provider.Search(ctx, query, 10, false)
if err != nil && strings.Contains(err.Error(), "failed to marshal Exa request") {
return nil, fmt.Errorf("internal bug in exa request construction: %w", err)
} Prevention
- Keep the request struct to JSON-safe types (string, bool, int, slices)
- Add a unit test that marshals a fully populated exaRequest
- Avoid custom MarshalJSON unless necessary; if present, unit-test its error paths
When it happens
Trigger: Calling Search when the exaRequest struct cannot be marshaled — practically only if the struct gains unsupported field types (e.g. chan, func, or a custom Marshaler that errors).
Common situations: After a code change adding a field with an unsupported type or a custom json.Marshaler that returns an error; essentially never in production with the current fixed schema.
Understand the failure class
Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.
Related errors
- failed to marshal schema: %v
- failed to set FAQ metadata: %w
- marshal credentials: %w
- parse rss credentials: %w
- decode poll response: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/e296d8a917dc6f5c.
Report an issue: GitHub.