googleapis/mcp-toolbox · error
unexpected non-string key for entry in '%s': %v
Error message
unexpected non-string key for entry in '%s': %v
What it means
transformDocs converts each top-level YAML entry (source, toolset, etc.) into a per-entry document slice. Every YAML map key must be a string because each key becomes the resource 'name'. This error is thrown when a key in a 'kind' section is not a string (e.g. a number or boolean key).
Source
Thrown at cmd/internal/config.go:359
name, _ = input[nameIndex].Value.(string)
}
// Warning is best effort: a caller without a logger in context still
// gets the conversion.
if logger, err := util.LoggerFromContext(ctx); err == nil {
logger.WarnContext(ctx, fmt.Sprintf("toolset %q: dropping description, which a toolset does not support; declare the collection as `kind: group` to keep it", name))
}
}
return migrated
}
// transformDocs transforms the configuration file from nested to flat format
// yaml.MapSlice will preserve the order in a map
func transformDocs(kind string, input yaml.MapSlice) ([]yaml.MapSlice, error) {
var transformed []yaml.MapSlice
for _, entry := range input {
entryName, ok := entry.Key.(string)
if !ok {
return nil, fmt.Errorf("unexpected non-string key for entry in '%s': %v", kind, entry.Key)
}
entryBody := processValue(entry.Value, kind == "toolset")
currentTransformed := yaml.MapSlice{
{Key: "kind", Value: kind},
{Key: "name", Value: entryName},
}
// Merge the transformed body into our result
if bodySlice, ok := entryBody.(yaml.MapSlice); ok {
currentTransformed = append(currentTransformed, bodySlice...)
} else {
return nil, fmt.Errorf("unable to convert entryBody to MapSlice")
}
transformed = append(transformed, currentTransformed)
}
return transformed, nil
}View on GitHub (pinned to 8cc6e09de2)
Solutions
- Quote the key so it parses as a string: `"12345": ...` instead of `12345: ...`
- Rename the entry key to a valid identifier string
- Check for YAML 1.1 boolean-like keys (on/off/yes/no) and quote them
Example fix
// before
sources:
8080:
kind: postgres
// after
sources:
"8080":
kind: postgres Defensive patterns
Strategy: validation
Validate before calling
func validateStringKeys(input yaml.MapSlice) error {
for _, e := range input {
if _, ok := e.Key.(string); !ok {
return fmt.Errorf("non-string key: %v", e.Key)
}
}
return nil
} Type guard
func isStringKey(k interface{}) bool { _, ok := k.(string); return ok } Try / catch
cfg, err := parser.ConvertConfig(ctx, data)
if err != nil {
if strings.Contains(err.Error(), "non-string key") {
// fix YAML keys, re-validate
}
return err
} Prevention
- Quote all YAML map keys, especially numeric or boolean-like ones (on, yes, 123)
- Run a YAML linter on config files before deploying
- Pin an editor schema for toolbox configs
When it happens
Trigger: A key under sources/tools/toolsets/authServices/prompts/groups in the toolbox YAML is a non-string scalar, e.g. `12345: ...` or `true: ...`, which yaml.MapSlice parses as a non-string type.
Common situations: Hand-edited YAML where a source name was written as a number (e.g. a port or an ID used directly as a key); copy-pasted JSON with numeric keys; YAML anchors or unquoted keys that parse as bool/int (e.g. `on:`, `yes:` which YAML 1.1 treats as booleans).
Related errors
- unable to convert entryBody to MapSlice
- unable to parse config file at %q: %w
- Invalid number "${item}" found in array for ${paramName} at
- doc %d: unexpected non-string key in input: %v
- doc %d: invalid config format at key %q: %w
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/57ec6e8dca922ce2.
Report an issue: GitHub.