googleapis/mcp-toolbox · error

error marshaling dynamic_fields: %w

Error message

error marshaling dynamic_fields: %w

What it means

ProcessQueryArgs accepts 'dynamic_fields' as a []any and serializes it to a JSON string for the Looker API. If json.Marshal fails on the slice (e.g. it contains values that cannot be marshaled such as channels or cyclic structures in Go callers), this wrapped error is returned.

Source

Thrown at internal/tools/looker/lookercommon/lookercommon.go:364

		}
		tz = tzname
	}

	var filterExpressionPtr *string
	if val, ok := paramsMap["filter_expression"]; ok && val != nil {
		if strVal, ok := val.(string); ok {
			filterExpressionPtr = &strVal
		} else {
			return nil, fmt.Errorf("'filter_expression' must be a string, got %T", val)
		}
	}

	var dynamicFieldsPtr *string
	if val, ok := paramsMap["dynamic_fields"]; ok && val != nil {
		if sliceVal, ok := val.([]any); ok && len(sliceVal) > 0 {
			jsonBytes, err := json.Marshal(sliceVal)
			if err != nil {
				return nil, fmt.Errorf("error marshaling dynamic_fields: %w", err)
			}
			jsonStr := string(jsonBytes)
			dynamicFieldsPtr = &jsonStr
		}
	}

	wq := v4.WriteQuery{
		Model:            paramsMap["model"].(string),
		View:             paramsMap["explore"].(string),
		Fields:           &fields,
		Pivots:           &pivots,
		Filters:          &filters,
		Sorts:            &sorts,
		QueryTimezone:    &tz,
		Limit:            &limit,
		FilterExpression: filterExpressionPtr,
		DynamicFields:    dynamicFieldsPtr,
	}

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Ensure dynamic_fields is a JSON-serializable array of objects, e.g. [{"name":"total","expression":"${sum}"}]
  2. Inspect the wrapped %w error for the specific unmarshalable value
  3. Rebuild the slice using only maps, slices, strings, numbers, and bools
  4. If coming from JSON input, this error is near-impossible — verify you are not pre-processing the slice into non-JSON types

Example fix

// before
paramsMap["dynamic_fields"] = []any{func() {}}
// after
paramsMap["dynamic_fields"] = []any{map[string]any{"name": "total", "expression": "sum(x)"}}
Defensive patterns

Strategy: try-catch

Validate before calling

if _, err := json.Marshal(dynamicFields); err != nil {
	// fix the slice before calling the tool
}

Type guard

func jsonSafe(v []any) bool { return json.NewDecoder(strings.NewReader(stringify(v))) == nil || marshalable(v) }
func marshalable(v any) bool { return json.Marshal(v) == nil }

Try / catch

df, err := json.Marshal(params["dynamic_fields"])
if err != nil {
	return fmt.Errorf("pre-check dynamic_fields marshal failed: %w", err)
}

Prevention

When it happens

Trigger: Passing a dynamic_fields slice containing unmarshalable values; in practice from Go callers embedding unsupported types into the []any; JSON-safe clients rarely trigger this.

Common situations: Programmatic Go callers building the params map with non-JSON types; corrupted callback/func values injected into the slice; extremely rare when parameters come from JSON decoding since decoded []any is always JSON-safe.

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/05319a6a167587bb. Report an issue: GitHub.