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

  1. Inspect the wrapped error for the unsupported type name and locate that field in tavilyRequest
  2. Convert the field to a JSON-encodable type or implement a correct MarshalJSON
  3. 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

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


AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01). Data as JSON: /api/errors/087d33125189741f. Report an issue: GitHub.