googleapis/mcp-toolbox · error
can't convert sorts to array of strings: %s
Error message
can't convert sorts to array of strings: %s
What it means
ProcessQueryArgs converts the raw 'sorts' parameter (declared as []any) into []string with parameters.ConvertAnySliceToTyped. Non-string elements (numbers, booleans, objects, nil) cause the conversion to fail and this wrapped error is returned before the query request is built.
Source
Thrown at internal/tools/looker/lookercommon/lookercommon.go:333
if len(k) >= 2 && (k[0] == '\'' || k[0] == '"') && k[0] == k[len(k)-1] {
newKey = k[1 : len(k)-1]
}
newVal := v
if s, ok := v.(string); ok && len(s) >= 2 &&
(s[0] == '\'' || s[0] == '"') && s[0] == s[len(s)-1] {
newVal = s[1 : len(s)-1]
}
processedFilters[newKey] = newVal
}
filters = processedFilters
p, err := parameters.ConvertAnySliceToTyped(paramsMap["pivots"].([]any), "string")
if err != nil {
return nil, fmt.Errorf("can't convert pivots to array of strings: %s", err)
}
pivots := p.([]string)
s, err := parameters.ConvertAnySliceToTyped(paramsMap["sorts"].([]any), "string")
if err != nil {
return nil, fmt.Errorf("can't convert sorts to array of strings: %s", err)
}
sorts := s.([]string)
limit := fmt.Sprintf("%v", paramsMap["limit"].(int))
var tz string
if paramsMap["tz"] != nil {
tz = paramsMap["tz"].(string)
} else {
tzname, err := tzlocal.RuntimeTZ()
if err != nil {
logger.ErrorContext(ctx, fmt.Sprintf("Error getting local timezone: %s", err))
tzname = "Etc/UTC"
}
tz = tzname
}
var filterExpressionPtr *string
if val, ok := paramsMap["filter_expression"]; ok && val != nil {View on GitHub (pinned to 8cc6e09de2)
Solutions
- Send sorts as an array of Looker sort strings of the form "<field_name> <asc|desc>", e.g. ["users.count desc"]
- Verify the parameter is an array, not a single string or object
- Convert programmatic values to strings before calling
- Inspect the upstream error in the message for the exact offending element
Example fix
// before
"sorts": [{"field": "users.count", "dir": "desc"}]
// after
"sorts": ["users.count desc"] Defensive patterns
Strategy: validation
Validate before calling
func validSorts(v any) bool {
s, ok := v.([]any)
if !ok { return false }
for _, e := range s {
str, ok := e.(string)
if !ok { return false }
parts := strings.Fields(str)
if len(parts) == 0 || len(parts) > 2 { return false }
}
return true
} Type guard
if s, ok := params["sorts"].([]any); ok && allStrings(s) { /* safe */ } Prevention
- Use Looker 'field direction' strings for sorts
- Convert structured sort objects to strings before invoking
- Keep numeric/boolean values out of array-of-string parameters
When it happens
Trigger: Invoking a Looker query tool with sorts containing non-string entries, e.g. sorts: [1] or sorts: [{"field":"x","dir":"asc"}] instead of ["users.count desc"].
Common situations: Clients passing structured sort objects rather than Looker's 'field direction' strings; agents generating numeric values; copy-pasted configs from other APIs with different sort formats.
Related errors
- can't convert fields to array of strings: %s
- can't convert pivots to array of strings: %s
- can't convert projectIds to array of strings: %w
- can't convert %s to array of strings: %w
- can't convert types to array of strings: %w
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/6bf44e515ef805fd.
Report an issue: GitHub.