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

  1. Send sorts as an array of Looker sort strings of the form "<field_name> <asc|desc>", e.g. ["users.count desc"]
  2. Verify the parameter is an array, not a single string or object
  3. Convert programmatic values to strings before calling
  4. 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

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


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