googleapis/mcp-toolbox · error

'model' must be a string, got %T

Error message

'model' must be a string, got %T

What it means

ProcessFieldArgs converts incoming parameter values to a map and asserts 'model' is a Go string. If the raw value has another dynamic type, the assertion fails and this error reports the actual %T type, since downstream Looker SDK calls require string model names.

Source

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

	return parameters.Parameters{
		modelParameter,
		exploreParameter,
		fieldsParameter,
		filtersParameter,
		pivotsParameter,
		sortsParameter,
		limitParameter,
		tzParameter,
		filterExpressionParameter,
		dynamicFieldsParameter,
	}
}

func ProcessFieldArgs(ctx context.Context, params parameters.ParamValues) (*string, *string, error) {
	mapParams := params.AsMap()
	model, ok := mapParams["model"].(string)
	if !ok {
		return nil, nil, fmt.Errorf("'model' must be a string, got %T", mapParams["model"])
	}
	explore, ok := mapParams["explore"].(string)
	if !ok {
		return nil, nil, fmt.Errorf("'explore' must be a string, got %T", mapParams["explore"])
	}
	return &model, &explore, nil
}

// escapeUnquotedParameterValue escapes Looker filter-expression metacharacters
// so the value reaches a type: unquoted parameter without being interpreted as
// a wildcard pattern. Looker treats `_` as a single-character wildcard and `%`
// as a multi-character wildcard, and rejects either inside unquoted-parameter
// values; `,` is the filter-expression value separator; `^` is the escape
// character itself. Already-escaped sequences (`^_`, `^%`, `^,`, `^^`) pass
// through unchanged, which keeps the function idempotent for callers that pass
// pre-escaped forms (e.g. round-tripping `default_filter_value` from the
// explore metadata). Lone metacharacters get a `^` prefix; lone `^` is doubled
// to `^^`. Walking rune-by-rune (not whole-string scanning) means a value with

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Send 'model' as a JSON string, e.g. {"model": "ecommerce"}.
  2. Ensure the parameter is present; do not omit it from the tool call.
  3. If calling from code, pass a plain Go string rather than an interface value.

Example fix

// before
{"model": 123, "explore": "orders"}
// after
{"model": "ecommerce", "explore": "orders"}
Defensive patterns

Strategy: validation

Validate before calling

// Client-side check before invoking
const model = "ecommerce";
if (typeof model !== "string" || model.length === 0) {
    throw new Error("'model' must be a non-empty string");
}

Type guard

m, ok := mapParams["model"]
if !ok {
    model, isStr := m.(string)
    if !isStr {
        return fmt.Errorf("model must be string, got %T", m)
    }
}

Try / catch

model, explore, err := lookercommon.ProcessFieldArgs(ctx, params)
if err != nil {
    return nil, util.NewInvalidArgumentError("check 'model' parameter: %v", err)
}

Prevention

When it happens

Trigger: Invoke receives params where mapParams["model"] is not a string (nil when the parameter is missing, a float/int from JSON numbers, or an object/array from a malformed request body).

Common situations: Client omitting 'model' or sending it as a number; MCP client serializing parameters with unexpected JSON types; calling the tool programmatically with wrong-typed arguments.

Related errors


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