googleapis/mcp-toolbox · error

%s missing 'kind' field or it is not a string

Error message

%s missing 'kind' field or it is not a string

What it means

This error is thrown by UnmarshalPrimitiveConfig while parsing a toolbox YAML file when a YAML document's top-level resource map does not contain a 'kind' key, or its value cannot be asserted as a string. 'kind' is required to route the document to the correct config type (source, tool, authService, etc.). When the file contains multiple YAML documents (len(file.Docs) > 1), this location-annotated variant is returned so the developer can find the offending document.

Source

Thrown at internal/server/config.go:205

	decoder := yaml.NewDecoder(bytes.NewReader(raw))
	for index, doc := range file.Docs {
		if doc == nil || doc.Body == nil {
			continue
		}
		docIndex := index + 1
		var resource map[string]any
		if err := decoder.DecodeFromNodeContext(ctx, doc.Body, &resource); err != nil {
			if len(file.Docs) > 1 {
				return nil, nil, nil, nil, nil, nil, fmt.Errorf("document %d: %s", docIndex, yaml.FormatError(err, false, false))
			}
			return nil, nil, nil, nil, nil, nil, fmt.Errorf("unable to decode YAML document: %s", yaml.FormatError(err, false, false))
		}
		var kind, name string
		var ok bool
		if kind, ok = resource["kind"].(string); !ok {
			if len(file.Docs) > 1 {
				return nil, nil, nil, nil, nil, nil, fmt.Errorf("%s missing 'kind' field or it is not a string", formatDocLocation(docIndex, keyToken(doc.Body, "kind"), doc.Body))
			}
			return nil, nil, nil, nil, nil, nil, fmt.Errorf("missing 'kind' field or it is not a string: %v", resource)
		}
		if name, ok = resource["name"].(string); !ok {
			// A `kind: group` may omit `name` to target the default nameless group;
			// every other resource requires a name.
			if kind == "group" {
				if rawName, present := resource["name"]; !present || rawName == nil {
					name, ok = "", true
				}
			}
		}
		if !ok {
			if len(file.Docs) > 1 {
				fallbackToken := keyToken(doc.Body, "name")
				if fallbackToken == nil {
					fallbackToken = keyToken(doc.Body, "kind")
				}

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Add a top-level 'kind' field with a string value (e.g. kind: tool) to the offending YAML document.
  2. If the file has multiple '---'-separated documents, check each document has its own kind at the document root, not nested.
  3. Verify kind is not quoted inconsistently or typed as a number/boolean; force a string (kind: "123").
  4. Run go run . --prebuilt my.yaml or a YAML linter to confirm the root structure parses to a map with kind.

Example fix

// before
sources:
  my-pg:
    kind: postgres
    host: localhost
// after
toolbox:
  kind: tool
  name: my-tool
sources:
  my-pg:
    kind: postgres
    host: localhost
Defensive patterns

Strategy: validation

Validate before calling

func validateTopLevelKind(doc map[string]any) error {
    v, ok := doc["kind"]
    if !ok {
        return fmt.Errorf("document missing required top-level 'kind' field")
    }
    if _, isStr := v.(string); !isStr {
        return fmt.Errorf("'kind' must be a string, got %T", v)
    }
    return nil
}

Type guard

kindVal, ok := doc["kind"]
isStringKind := ok && func(v any) bool { _, isStr := v.(string); return isStr }(kindVal)

Prevention

When it happens

Trigger: Calling ParseConfig (via UnmarshalPrimitiveConfig) on YAML where a document's root is a map with no 'kind' key, or where kind's value is a non-string (e.g. kind: 123, kind: true, kind: [tool]).

Common situations: Hand-written YAML files omitting the kind field; copying a snippet without its kind line; accidental indentation causing kind to nest under another key; CI tooling generating YAML with numeric kinds.

Related errors


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