{"record":{"id":"b983586ca92eeb71","repo":"grpc-ecosystem/grpc-gateway","slug":"unexpected-number-of-yaml-nodes","errorCode":null,"errorMessage":"unexpected number of yaml nodes","messagePattern":"unexpected number of yaml nodes","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"protoc-gen-openapiv2/internal/genopenapi/generator.go","lineNumber":187,"sourceCode":"//\t\tvar node yaml.Node\n//\t\tif err := node.Encode(pio); err != nil {\n//\t\t\treturn nil, err\n//\t\t}\n//\t\treturn &node, nil\n//\t}\nfunc (pio *openapiPathItemObject) toYAMLNode() (*yaml.Node, error) {\n\tvar doc yaml.Node\n\tvar buf bytes.Buffer\n\tec := yaml.NewEncoder(&buf)\n\tec.SetIndent(2)\n\tif err := ec.Encode(pio); err != nil {\n\t\treturn nil, err\n\t}\n\tif err := yaml.Unmarshal(buf.Bytes(), &doc); err != nil {\n\t\treturn nil, err\n\t}\n\tif len(doc.Content) == 0 {\n\t\treturn nil, errors.New(\"unexpected number of yaml nodes\")\n\t}\n\treturn doc.Content[0], nil\n}\n\nfunc (so openapiInfoObject) MarshalJSON() ([]byte, error) {\n\ttype alias openapiInfoObject\n\treturn extensionMarshalJSON(alias(so), so.extensions)\n}\n\nfunc (so openapiInfoObject) MarshalYAML() (interface{}, error) {\n\ttype Alias openapiInfoObject\n\n\treturn struct {\n\t\tExtension map[string]interface{} `yaml:\",inline\"`\n\t\tAlias     `yaml:\",inline\"`\n\t}{\n\t\tExtension: extensionsToMap(so.extensions),\n\t\tAlias:     Alias(so),","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/grpc-ecosystem/grpc-gateway/blob/a58a4436a376a4bcc7d8f10c4d4f919a8438bba9/protoc-gen-openapiv2/internal/genopenapi/generator.go#L169-L205","documentation":"toYAMLNode converts a Go value to a YAML node by marshalling it to YAML text and unmarshalling it back into a document node. If the unmarshalled document has zero content nodes (len(doc.Content) == 0), it returns \"unexpected number of yaml nodes\". This happens when the value marshals to an empty or non-node YAML document, so the generator cannot attach it as an OpenAPI extension value.","triggerScenarios":"Calling toYAMLNode (indirectly via openapiInfoObject/extension handling when building OpenAPI output) with a value that serializes to an empty YAML document — e.g. a nil value, empty document, or malformed extension value used for the OpenAPI spec.","commonSituations":"Setting an OpenAPI option/extension (via .proto options like openapiv2_swagger or openapiv2_operation, or programmatically) to a value that produces empty YAML output, or feeding generated YAML from another tool that emits nothing.","solutions":["Ensure the value passed to toYAMLNode (the extension/option value) is a non-nil, marshalled object that produces a valid YAML mapping or sequence.","Inspect the proto option or extension payload feeding the OpenAPI output; fix empty/invalid values.","If constructing extensions in code, verify yaml.Marshal of the value produces non-empty output before calling toYAMLNode.","Check for version mismatches between grpc-gateway and gopkg.in/yaml dependency versions that can affect marshalling."],"exampleFix":"// before\nvar ext map[string]interface{}\nnode, err := toYAMLNode(ext) // ext is nil -> empty doc -> error\n// after\nif len(ext) == 0 {\n    return nil\n}\nnode, err := toYAMLNode(ext)","handlingStrategy":"validation","validationCode":"buf, _ := yaml.Marshal(v)\nif len(bytes.TrimSpace(buf)) == 0 {\n    return fmt.Errorf(\"refusing to convert empty YAML value: %T\", v)\n}","typeGuard":"func isNonEmptyYAMLValue(v interface{}) bool {\n    if v == nil { return false }\n    out, err := yaml.Marshal(v)\n    return err == nil && len(bytes.TrimSpace(out)) > 0\n}","tryCatchPattern":"node, err := toYAMLNode(v)\nif err != nil {\n    return fmt.Errorf(\"invalid extension value %v: %w\", v, err)\n}","preventionTips":["Never pass nil or empty values as OpenAPI extension/option payloads.","Validate proto option payloads referenced by openapiv2 annotations.","Pin gopkg.in/yaml dependency versions consistently."],"tags":["yaml","openapi","serialization","code-generation"],"backgroundTag":"empty-yaml-document","analyzedSha":"a58a4436a376a4bcc7d8f10c4d4f919a8438bba9","analyzedAt":"2026-09-02T10:28:31.537Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T16:17:10.729Z"}