googleapis/mcp-toolbox · error
'explore' must be a string, got %T
Error message
'explore' must be a string, got %T
What it means
Runtime type check in ProcessFieldArgs: the invocation's `explore` parameter is not a string (the message reports the actual Go type received, e.g. map or float64), so the target Looker explore cannot be identified.
Source
Thrown at internal/tools/looker/lookercommon/lookercommon.go:179
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
// both an already-escaped sequence and an unescaped metacharacter gets each
// half handled correctly — e.g. `first^_touch_v2` becomes `first^_touch^_v2`.
func escapeUnquotedParameterValue(value string) string {
var sb strings.BuilderView on GitHub (pinned to 8cc6e09de2)
Solutions
- Send 'explore' as a JSON string, e.g. {"explore": "order_items"}.
- Ensure both 'model' and 'explore' are present in the tool call.
- Validate the request payload types client-side before invoking.
Example fix
// before
{"model": "ecommerce", "explore": true}
// after
{"model": "ecommerce", "explore": "order_items"}
Defensive patterns
Strategy: validation
Validate before calling
// Client-side check before invoking
const explore = "order_items";
if (typeof explore !== "string" || explore.length === 0) {
throw new Error("'explore' must be a non-empty string");
} Type guard
e, ok := mapParams["explore"]
explore, isStr := e.(string)
if !ok || !isStr {
return fmt.Errorf("explore must be string, got %T", e)
} Try / catch
model, explore, err := lookercommon.ProcessFieldArgs(ctx, params)
if err != nil {
return nil, util.NewInvalidArgumentError("check 'explore' parameter: %v", err)
} Prevention
- Always send both model and explore as strings in the same payload.
- Validate parameter types before invoking the tool programmatically.
- Use typed SDK wrappers that enforce string arguments at compile time.
When it happens
Trigger: Invoke receives params where mapParams["explore"] is nil (missing) or a non-string dynamic value (number, bool, array).
Common situations: Client omitting 'explore'; JSON payload typing explore as a number; programmatic invocation passing the wrong type; template interpolation injecting a non-string.
Related errors
- 'model' must be a string, got %T
- unable to bind: %w
- invalid source for %q tool: source %q is not a compatible ty
- invalid source for %q tool: source %q is not a compatible ty
- can't convert fields to array of strings: %s
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/eed41fd903a06763.
Report an issue: GitHub.