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

  1. Quote the key so it parses as a string: `"12345": ...` instead of `12345: ...`
  2. Rename the entry key to a valid identifier string
  3. 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

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


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