googleapis/mcp-toolbox · critical
document %d: %s
Error message
document %d: %s
What it means
When the tools file contains multiple YAML documents (--- separated), a per-document decode failure is reported as `document %d: <yaml error>` with the 1-based document index. It wraps yaml.FormatError output so the offending line inside that document can be located. A single-document file uses the more generic message instead (error 159).
Source
Thrown at internal/server/config.go:197
// take precedence regardless of document order.
var toolsetGroups map[string]group.GroupConfig
// 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
- Locate the Nth document (count `---` separators) and fix the reported YAML error inside it
- Ensure every document is a YAML mapping with kind/name keys
- Temporarily split documents into separate files to isolate the broken one
- Validate each document independently with a YAML parser
Example fix
// before docs: --- - kind: tool # document is a list, not a mapping // after docs: --- kind: tool name: my-tool
Defensive patterns
Strategy: validation
Validate before calling
const docs = fs.readFileSync('tools.yaml','utf8').split(/^---$/m);
docs.forEach((d, i) => {
const parsed = require('yaml').parse(d);
if (typeof parsed !== 'object' || Array.isArray(parsed) || parsed === null)
throw new Error(`document ${i+1} must be a mapping`);
if (!('kind' in parsed)) throw new Error(`document ${i+1} missing 'kind'`);
}); Prevention
- Validate each `---`-separated document is a mapping with kind/name
- Split multi-doc files when debugging to isolate failures
- Lint multi-document YAML with yq or a parser in CI
When it happens
Trigger: A multi-document tools.yaml where one document's body cannot be decoded into map[string]any — e.g. a document that is a list/scalar instead of a mapping, or node-level type mismatches during DecodeFromNodeContext.
Common situations: Appending a second config document with `---` that has a structural error, generating configs programmatically producing non-mapping documents, merging config files incorrectly.
Related errors
- unable to parse YAML: %s
- unable to decode YAML document: %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/5ba3f2a9f35319a4.
Report an issue: GitHub.