googleapis/mcp-toolbox · critical
unable to decode YAML document: %s
Error message
unable to decode YAML document: %s
What it means
When the tools file has a single YAML document and yaml.Decoder.DecodeFromNodeContext fails to decode it into a resource map, the config loader aborts with `unable to decode YAML document: <formatted error>`. Unlike the multi-document case, no document index is shown since there is only one.
Source
Thrown at internal/server/config.go:199
// promptset configs is not yet supported
file, err := parser.ParseBytes(raw, 0)
if err != nil {
return nil, nil, nil, nil, nil, nil, fmt.Errorf("unable to parse YAML: %s", yaml.FormatError(err, false, false))
}
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
}
}
}View on GitHub (pinned to 8cc6e09de2)
Solutions
- Ensure the top level of the file is a mapping (sources:, tools:, etc.), not a list or scalar
- Restore the full file structure (kind/name on resources) from the docs examples
- Check the embedded yaml.FormatError message for the failing line/column
- Validate the file parses to an object: `yq eval '.' tools.yaml`
Example fix
// before
- kind: source
name: my-pg
// after
sources:
my-pg:
kind: postgres Defensive patterns
Strategy: validation
Validate before calling
const parsed = require('yaml').parse(fs.readFileSync('tools.yaml','utf8'));
if (typeof parsed !== 'object' || Array.isArray(parsed) || parsed === null) {
throw new Error('tools.yaml root must be a mapping (sources:, tools:, ...)');
} Prevention
- Keep the top-level structure as a mapping with sources/tools keys
- Restore from documented examples after edits
- Validate with `yq eval '.' tools.yaml` before starting the server
When it happens
Trigger: Loading a single-document tools.yaml whose root is not decodable into map[string]any (e.g. the file starts with a list or scalar), or YAML content that parses but fails node decoding due to duplicate keys/type conflicts.
Common situations: Replacing tools.yaml contents with a plain list of tools, truncating the file so only a fragment remains, accidentally saving logs or JSON into the tools file.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- unable to parse YAML: %s
- document %d: %s
- environment variable not found: %s
- environment variables not found: - %s
- error parsing environment variables: %s
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/ea8150e341a879f0.
Report an issue: GitHub.