googleapis/mcp-toolbox · error

failed to marshal payload: %w

Error message

failed to marshal payload: %w

What it means

getStream serializes the Conversational Analytics request payload (CAPayload) to JSON before POSTing it. If json.Marshal fails — e.g. the payload contains a value that cannot be marshaled such as a channel, func, or unsupported custom type — the function returns this wrapped error without making the HTTP call.

Source

Thrown at internal/tools/looker/lookerconversationalanalytics/lookerconversationalanalytics.go:428

	ResultNaturalLanguage string `json:"resultNaturalLanguage,omitempty"`
	ResultCsvData         string `json:"resultCsvData,omitempty"`
	ResultReferenceData   string `json:"resultReferenceData,omitempty"`
	Error                 string `json:"error,omitempty"`
}
type AnalysisMessage struct {
	Query         AnalysisQuery `json:"query,omitempty"`
	ProgressEvent AnalysisEvent `json:"progressEvent,omitempty"`
}

// ErrorResponse represents an error message from the API.
type ErrorMessage struct {
	Text string `json:"text"`
}

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

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(payloadBytes))
	if err != nil {
		return nil, 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 nil, 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. Inspect the wrapped %w error to find the unmarshalable field
  2. Ensure all CAPayload fields are JSON-safe (strings, slices, maps, numbers)
  3. Remove or convert custom types to primitives before building the payload
  4. Add a unit test marshaling your payload construction path

Example fix

// before
payload.Data = make(chan int)
// after
payload.Data = map[string]any{"key": "value"}
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

resp, err := getStream(ctx, client, url, payload, headers)
if err != nil {
	var mk *json.MarshalTypeError
	if errors.As(err, &mk) {
		log.Printf("bad field %s at offset %d", mk.Field, mk.Offset)
	}
	return err
}

Prevention

When it happens

Trigger: Constructing a CAPayload whose nested fields (userQueryWithcontext, exploreReferences, options, etc.) include non-JSON-marshalable Go values; programmatic Go callers building the payload manually.

Common situations: Custom Go code extending the payload with unsupported field types; cyclic data structures; fields populated from goroutine-unsafe shared state.

Understand the failure class

Background: "JSON serialization failed", "not JSON serializable", "Failed to serialize": why JSON marshaling errors happen and how to fix them — this error's family across 46 libraries.

Related errors


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/6c7e480220a94283. Report an issue: GitHub.