vxcontrol/pentagi · error · Fatal
failed to marshal request body: %v
Error message
failed to marshal request body: %v
What it means
json.Marshal of the tavilyRequest struct failed inside tavily.search(); the searcher returns a Fatal error. With the current struct (strings/ints/bools) this cannot occur naturally — it appears only when a non-encodable field or failing MarshalJSON method is introduced.
Source
Thrown at backend/pkg/tools/searchers/tavily.go:121
func (t *tavily) search(ctx context.Context, query string, maxResults int) (string, error) {
client, err := system.GetHTTPClient(t.cfg)
if err != nil {
return "", Fatal(fmt.Errorf("failed to create http client: %w", err))
}
reqPayload := tavilyRequest{
Query: query,
ApiKey: t.apiKey(),
Topic: "general",
SearchDepth: "advanced",
IncludeImages: false,
IncludeAnswer: true,
IncludeRawContent: true,
MaxResults: maxResults,
}
reqBody, err := json.Marshal(reqPayload)
if err != nil {
return "", Fatal(fmt.Errorf("failed to marshal request body: %v", err))
}
req, err := http.NewRequest(http.MethodPost, tavilyURL, bytes.NewBuffer(reqBody))
if err != nil {
return "", Fatal(fmt.Errorf("failed to build request: %v", err))
}
req = req.WithContext(ctx)
req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
return "", Retryable(fmt.Errorf("failed to do request: %v", err), 0)
}
defer resp.Body.Close()
return t.parseHTTPResponse(ctx, resp)
}View on GitHub (pinned to ea665308ba)
Solutions
- Inspect the wrapped error for the unsupported type name and locate that field in tavilyRequest
- Convert the field to a JSON-encodable type or implement a correct MarshalJSON
- Run a unit test marshaling a fully populated tavilyRequest to catch this before runtime
Example fix
// before
Payload tavilyRequest{..., Callback: make(chan int)} // unsupported
// after
Payload tavilyRequest{..., MaxResults: maxResults} Defensive patterns
Strategy: validation
Validate before calling
if _, err := json.Marshal(reqPayload); err != nil {
log.Fatalf("tavily payload not encodable: %v", err)
} Type guard
func isJSONEncodable(v any) bool { var b bytes.Buffer; enc := json.NewEncoder(&b); return enc.Encode(v) == nil } Try / catch
reqBody, err := json.Marshal(reqPayload)
if err != nil {
return "", Fatal(fmt.Errorf("failed to marshal request body: %v", err))
} Prevention
- Use %w instead of %v so errors.As/Is unwrapping works
- Unit-test marshaling of tavilyRequest with all fields populated
- Restrict payload structs to JSON-primitive field types
When it happens
Trigger: search() marshals reqPayload (Query, ApiKey, Topic, IncludeAnswer, IncludeRawContent, MaxResults); fails if a new field of unsupported type (chan, func, complex) or a broken MarshalJSON is added to tavilyRequest.
Common situations: A developer adds a custom field type or time.Time-like wrapper with an erroring MarshalJSON to tavilyRequest; caught immediately on first search.
Related errors
- failed to marshal provider config: %w
- failed to marshal request body: %w
- failed to marshal request body: %v
- knowledge: marshal cmetadata: %w
- failed to unmarshal search arguments: %w
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/087d33125189741f.
Report an issue: GitHub.