googleapis/mcp-toolbox · error
missing 'kind' field or it is not a string: %v
Error message
missing 'kind' field or it is not a string: %v
What it means
This is the single-document variant of the missing-'kind' error: when the YAML file contains exactly one document, UnmarshalPrimitiveConfig returns an error that includes the raw parsed resource map (%v) instead of a document-location prefix. It means the top-level map has no 'kind' key or the value is not a string.
Source
Thrown at internal/server/config.go:207
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")
}
return nil, nil, nil, nil, nil, nil, fmt.Errorf("%s missing 'name' field or it is not a string", formatDocLocation(docIndex, fallbackToken, doc.Body))
}View on GitHub (pinned to 8cc6e09de2)
Solutions
- Add 'kind: <source|tool|authService|group|...>' as a top-level key in the YAML document.
- Inspect the map printed in the error to confirm what was actually parsed; ensure kind sits at the root, not nested.
- If kind exists but parses oddly (e.g. null from an anchor), inline its literal string value.
- Check indentation so the root is a flat mapping of keys including kind.
Example fix
// before (file tools.yaml) name: my-source kind: 123 // after kind: source name: my-source
Defensive patterns
Strategy: validation
Validate before calling
docs := strings.Split(yamlText, "\n---")
if len(docs) == 1 {
var root map[string]any
if err := yaml.Unmarshal([]byte(yamlText), &root); err != nil { panic(err) }
if k, ok := root["kind"].(string); !ok || k == "" {
return fmt.Errorf("single-doc config needs a string 'kind', parsed root: %v", root)
}
} Type guard
k, ok := root["kind"]
hasStringKind := ok && func(v any) bool { s, isStr := v.(string); return isStr && s != "" }(k) Try / catch
if err := server.ParseConfig(ctx, ...); err != nil {
if strings.Contains(err.Error(), "missing 'kind'") {
log.Fatalf("config error: add a top-level 'kind' string to %s: %v", toolsFile, err)
}
return err
} Prevention
- Copy complete config examples from the docs, not fragments.
- Keep kind as the first key in every YAML document.
- Avoid YAML anchors/aliases for the kind key; inline the literal string.
- Lint YAML files with a schema that requires kind.
When it happens
Trigger: Calling ParseConfig on a single-document YAML file whose root map lacks a 'kind' key or has a non-string kind value; the offending map is printed in the error.
Common situations: New users writing their first tools.yaml without kind; editors stripping or reordering keys; pasting a partial config fragment; YAML anchors causing kind to resolve to null.
Related errors
- doc %d: unexpected non-string key in input: %v
- doc %d: invalid config format at key %q: %w
- doc %d: invalid config format at key %q: expected nested for
- %s missing 'kind' field or it is not a string
- %s missing 'name' field or it is not a string
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/95e140b6f5be1756.
Report an issue: GitHub.