{"record":{"id":"eed41fd903a06763","repo":"googleapis/mcp-toolbox","slug":"explore-must-be-a-string-got-t","errorCode":null,"errorMessage":"'explore' must be a string, got %T","messagePattern":"'explore' must be a string, got %T","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/tools/looker/lookercommon/lookercommon.go","lineNumber":179,"sourceCode":"\t\tfiltersParameter,\n\t\tpivotsParameter,\n\t\tsortsParameter,\n\t\tlimitParameter,\n\t\ttzParameter,\n\t\tfilterExpressionParameter,\n\t\tdynamicFieldsParameter,\n\t}\n}\n\nfunc ProcessFieldArgs(ctx context.Context, params parameters.ParamValues) (*string, *string, error) {\n\tmapParams := params.AsMap()\n\tmodel, ok := mapParams[\"model\"].(string)\n\tif !ok {\n\t\treturn nil, nil, fmt.Errorf(\"'model' must be a string, got %T\", mapParams[\"model\"])\n\t}\n\texplore, ok := mapParams[\"explore\"].(string)\n\tif !ok {\n\t\treturn nil, nil, fmt.Errorf(\"'explore' must be a string, got %T\", mapParams[\"explore\"])\n\t}\n\treturn &model, &explore, nil\n}\n\n// escapeUnquotedParameterValue escapes Looker filter-expression metacharacters\n// so the value reaches a type: unquoted parameter without being interpreted as\n// a wildcard pattern. Looker treats `_` as a single-character wildcard and `%`\n// as a multi-character wildcard, and rejects either inside unquoted-parameter\n// values; `,` is the filter-expression value separator; `^` is the escape\n// character itself. Already-escaped sequences (`^_`, `^%`, `^,`, `^^`) pass\n// through unchanged, which keeps the function idempotent for callers that pass\n// pre-escaped forms (e.g. round-tripping `default_filter_value` from the\n// explore metadata). Lone metacharacters get a `^` prefix; lone `^` is doubled\n// to `^^`. Walking rune-by-rune (not whole-string scanning) means a value with\n// both an already-escaped sequence and an unescaped metacharacter gets each\n// half handled correctly — e.g. `first^_touch_v2` becomes `first^_touch^_v2`.\nfunc escapeUnquotedParameterValue(value string) string {\n\tvar sb strings.Builder","sourceCodeStart":161,"sourceCodeEnd":197,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/tools/looker/lookercommon/lookercommon.go#L161-L197","documentation":"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.","triggerScenarios":"Invoke receives params where mapParams[\"explore\"] is nil (missing) or a non-string dynamic value (number, bool, array).","commonSituations":"Client omitting 'explore'; JSON payload typing explore as a number; programmatic invocation passing the wrong type; template interpolation injecting a non-string.","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."],"exampleFix":"// before\n{\"model\": \"ecommerce\", \"explore\": true}\n// after\n{\"model\": \"ecommerce\", \"explore\": \"order_items\"}\n","handlingStrategy":"validation","validationCode":"// Client-side check before invoking\nconst explore = \"order_items\";\nif (typeof explore !== \"string\" || explore.length === 0) {\n    throw new Error(\"'explore' must be a non-empty string\");\n}","typeGuard":"e, ok := mapParams[\"explore\"]\nexplore, isStr := e.(string)\nif !ok || !isStr {\n    return fmt.Errorf(\"explore must be string, got %T\", e)\n}","tryCatchPattern":"model, explore, err := lookercommon.ProcessFieldArgs(ctx, params)\nif err != nil {\n    return nil, util.NewInvalidArgumentError(\"check 'explore' parameter: %v\", err)\n}","preventionTips":["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."],"tags":["parameters","type-mismatch","looker"],"backgroundTag":"parameter-type-mismatch","analyzedSha":"8cc6e09de2ad7b8bffc77751799585a1401a48eb","analyzedAt":"2026-09-05T01:10:36.887Z","contentChangedAt":"2026-09-05T01:10:36.887Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}