googleapis/mcp-toolbox · error

error marshalling message: %w

Error message

error marshalling message: %w

What it means

After processing all streamed messages, getStream re-marshals each processed map[string]any back to JSON to build newline-delimited output. Any per-message marshal failure produces this error. Since inputs are already map[string]any from valid JSON, this is nearly impossible in stock code and signals data corruption or non-serializable values injected by custom processing.

Source

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

			dataMsgIdx = len(messages)
		} else if sm, ok := msg["systemMessage"].(map[string]any); ok {
			// 2. If it's a system message, unwrap it.
			processedMsg = sm
		} else {
			// 3. Otherwise (e.g. error), pass it through raw.
			processedMsg = msg
		}

		if processedMsg != nil {
			messages = append(messages, processedMsg)
		}
	}

	var acc strings.Builder
	for i, msg := range messages {
		jsonBytes, err := json.Marshal(msg)
		if err != nil {
			return "", fmt.Errorf("error marshalling message: %w", err)
		}
		acc.Write(jsonBytes)
		if i < len(messages)-1 {
			acc.WriteString("\n")
		}
	}

	return acc.String(), nil
}

// extractDataResult attempts to find the result.data deep inside the generic map.
func extractDataResult(msg map[string]any) map[string]any {
	sm, ok := msg["systemMessage"].(map[string]any)
	if !ok {
		return nil
	}
	data, ok := sm["data"].(map[string]any)
	if !ok {

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Audit any local modifications to the message-processing functions (formatDataRetrieved, extractDataResult) for values that json.Marshal cannot handle (NaN, Inf, channels, funcs).
  2. Sanitize numeric results (replace NaN/Inf with null) before appending messages.
  3. Rebuild against upstream toolbox code to rule out local drift, then retry.

Example fix

// before: injected NaN float in processed message
msg["score"] = math.NaN()
// after
if math.IsNaN(score) { msg["score"] = nil } else { msg["score"] = score }
Defensive patterns

Strategy: validation

Validate before calling

for k, v := range msg {
    if !isJSONSafe(v) {
        return fmt.Errorf("field %q not JSON-serializable: %T", k, v)
    }
}

Type guard

func isJSONSafe(v any) bool {
    switch t := v.(type) {
    case nil, string, bool, int, int64, float64:
        if f, ok := t.(float64); ok && (math.IsNaN(f) || math.IsInf(f, 0)) {
            return false
        }
        return true
    case []any:
        for _, e := range t { if !isJSONSafe(e) { return false } }
        return true
    case map[string]any:
        for _, e := range t { if !isJSONSafe(e) { return false } }
        return true
    default:
        return false
    }
}

Try / catch

result, err := tool.Invoke(ctx, params)
if err != nil && strings.Contains(err.Error(), "error marshalling message") {
    return fmt.Errorf("processed message contains non-serializable data: %w", err)
}

Prevention

When it happens

Trigger: Invoke on the tool when a processed message map contains a value encoding/json cannot serialize — realistically only after local modifications to formatDataRetreated/extractDataResult or similar processing functions inject unsupported values (channels, funcs, NaN floats).

Common situations: Custom forks adding computed fields with unsupported Go types; injected NaN/Inf floats from custom formatting logic; corrupted message maps from a modified processing pipeline.

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/4c23ee04bbf2969b. Report an issue: GitHub.