googleapis/mcp-toolbox · error

failed to marshal payload: %w

Error message

failed to marshal payload: %w

What it means

getStream marshals the Conversational Analytics API request payload (CAPayload) to JSON before sending the POST. This error wraps any failure from json.Marshal of that payload. In practice this is rare because CAPayload contains only JSON-serializable fields; it indicates the payload structure became non-marshalable (e.g. custom types with unsupported fields).

Source

Thrown at internal/tools/bigquery/bigqueryconversationalanalytics/bigqueryconversationalanalytics.go:272

		// getStream wraps network errors or non-200 responses
		return nil, util.NewClientServerError("failed to get response from conversational analytics API", http.StatusInternalServerError, err)
	}

	return response, nil
}

func (t Tool) RequiresClientAuthorization(source sources.Source) (bool, error) {
	s, ok := source.(compatibleSource)
	if !ok {
		return false, fmt.Errorf("invalid source for %q tool: source %q is not a compatible type", t.Cfg.Type, t.Cfg.Source)
	}
	return s.UseClientAuthorization(), nil
}

func getStream(client *http.Client, url string, payload CAPayload, headers map[string]string, maxRows int) (string, error) {
	payloadBytes, err := json.Marshal(payload)
	if err != nil {
		return "", fmt.Errorf("failed to marshal payload: %w", err)
	}

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(payloadBytes))
	if err != nil {
		return "", fmt.Errorf("failed to create request: %w", err)
	}
	for k, v := range headers {
		req.Header.Set(k, v)
	}

	resp, err := client.Do(req)
	if err != nil {
		return "", fmt.Errorf("failed to send request: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(resp.Body)

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Check for local modifications or forks that added non-JSON-serializable fields to CAPayload/Message and fix their types.
  2. Ensure the user text and table references passed to Invoke contain no unsupported characters/types by logging the payload before marshaling.
  3. Rebuild against the upstream version of the toolbox to rule out local drift, then retry Invoke.

Example fix

// before: cyclic/unsupported field in payload
type CAPayload struct { Messages []Message; Callback func() }
// after: keep payload JSON-only
type CAPayload struct { Messages []Message `json:"messages"`; InlineContext InlineContext `json:"inlineContext"`; ClientIdEnum string `json:"clientIdEnum"` }
Defensive patterns

Strategy: try-catch

Validate before calling

if _, err := json.Marshal(payload); err != nil {
    return fmt.Errorf("payload not serializable: %w", err)
}

Try / catch

result, err := tool.Invoke(ctx, params)
if err != nil && strings.Contains(err.Error(), "failed to marshal payload") {
    log.Printf("payload construction bug: %v", err)
    return fmt.Errorf("internal payload error: %w", err)
}

Prevention

When it happens

Trigger: Calling Invoke on the bigquery-conversational-analytics tool when the constructed CAPayload (messages, inlineContext, clientIdEnum) cannot be serialized by encoding/json — e.g. a corrupted/modified payload type containing channels, funcs, or cycles.

Common situations: Custom forks that added unsupported field types to CAPayload or Message; Go version/library changes changing marshal behavior; transient logic bugs injecting nil or cyclic data into 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 googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/259cebf020c9e81e. Report an issue: GitHub.