googleapis/mcp-toolbox · error

unable to convert entryBody to MapSlice

Error message

unable to convert entryBody to MapSlice

What it means

After processing an entry's value with processValue, transformDocs expects the result to be a yaml.MapSlice so it can merge it into the transformed document. This error is thrown when processValue returns something else (e.g. a different map type or scalar) for an entry body.

Source

Thrown at cmd/internal/config.go:372

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
}

// processValue recursively looks for MapSlices to rename 'kind' -> 'type'
func processValue(v any, isToolset bool) any {
	switch val := v.(type) {
	case yaml.MapSlice:
		// creating a new MapSlice is safer for recursive transformation
		newVal := make(yaml.MapSlice, len(val))
		for i, item := range val {
			// Perform renaming
			if item.Key == "kind" {
				item.Key = "type"
			}
			// Recursive call for nested values (e.g., nested objects or lists)

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Ensure each entry body is a YAML mapping with fields like kind/description/parameters
  2. Check indentation so the entry's fields nest under the entry name
  3. Unmarshal with yaml.MapSlice (v2) semantics; avoid mixing yaml.v3 types

Example fix

// before
sources:
  mypg: postgres
// after
sources:
  mypg:
    kind: postgres
    uri: ...
Defensive patterns

Strategy: validation

Validate before calling

for name, val := range section {
  if _, ok := val.(map[interface{}]interface{}); !ok {
    return fmt.Errorf("entry %v must be a mapping, got %T", name, val)
  }
}

Type guard

func isMapSlice(v interface{}) bool { _, ok := v.(yaml.MapSlice); return ok }

Try / catch

cfg, err := parser.ConvertConfig(ctx, data)
if err != nil {
  if strings.Contains(err.Error(), "entryBody to MapSlice") {
    // entry body is not a mapping; inspect YAML structure
  }
  return err
}

Prevention

When it happens

Trigger: The value of an entry under a kind section is not a mapping that processValue converts to yaml.MapSlice — e.g. a source defined as a scalar (`sources: mypg: postgres`) or a list instead of a map of fields.

Common situations: Malformed config where a source/tool definition body was accidentally replaced with a plain string or list, often from YAML indentation mistakes that flatten the structure.

Related errors


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