vxcontrol/pentagi · error · Fatal

failed to marshal request body: %v

Error message

failed to marshal request body: %v

What it means

traversaal.search returns Fatal 'failed to marshal request body: %v' when json.Marshal of the {"query": string} payload fails. With a plain string field this is practically unreachable — encoding a struct with one string cannot fail — so its presence signals something unusual (custom MarshalJSON, memory corruption, or refactor to complex types).

Source

Thrown at backend/pkg/tools/searchers/traversaal.go:83

		return "", err
	}

	return result, nil
}

func (t *traversaal) search(ctx context.Context, query string) (string, error) {
	client, err := system.GetHTTPClient(t.cfg)
	if err != nil {
		return "", Fatal(fmt.Errorf("failed to create http client: %w", err))
	}

	reqBody, err := json.Marshal(struct {
		Query string `json:"query"`
	}{
		Query: query,
	})
	if err != nil {
		return "", Fatal(fmt.Errorf("failed to marshal request body: %v", err))
	}

	req, err := http.NewRequest(http.MethodPost, traversaalURL, 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")
	req.Header.Set("x-api-key", t.apiKey())

	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(resp)

View on GitHub (pinned to ea665308ba)

Solutions

  1. Inspect the wrapped %v message for the unsupported type name.
  2. Remove non-serializable fields (channels, funcs, cycles) from the request struct.
  3. Add a unit test marshaling a representative request payload.
  4. No runtime fix needed for the current single-string struct — treat occurrences as a code bug.

Example fix

// before: unsupported field added
struct{ Query string; CB chan int `json:"-"` }
// after: keep payload JSON-serializable only
struct{ Query string `json:"query"` }{Query: query}
Defensive patterns

Strategy: validation

Validate before calling

payload := struct{ Query string `json:"query"` }{Query: query}
if b, err := json.Marshal(payload); err != nil || len(b) == 0 {
    return errors.New("traversaal request payload not serializable")
}

Try / catch

result, err := traversaalSearcher.Handle(ctx, req)
if err != nil && strings.Contains(err.Error(), "failed to marshal request body") {
    return "", fmt.Errorf("code bug: non-serializable payload: %w", err)
}

Prevention

When it happens

Trigger: json.Marshal(struct{ Query string `json:"query"` }{Query: query}) returns an error before building the http.Request in search().

Common situations: A refactor added unsupported types (channels, funcs, cyclic pointers) to the request struct; extremely rare for the current one-field struct; custom marshaling bugs after extending the payload.

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


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