{"record":{"id":"1638bc8568b0bbe9","repo":"JuliusBrussee/caveman","slug":"multiple-yaml-documents-are-not-allowed","errorCode":null,"errorMessage":"multiple YAML documents are not allowed","messagePattern":"multiple YAML documents are not allowed","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shared/platform/catalog/catalog.go","lineNumber":312,"sourceCode":"\t\tloadErr = fmt.Errorf(\"catalog %s: %w\", path, err)\n\t}\n\tentries = []Entry{}\n}\n\n// DecodeAndValidate strictly parses a catalog. Unknown YAML fields, duplicate\n// provider/model/region rows, invalid URLs/timestamps, and unsafe prices reject\n// the entire file; runtime must never load a plausible partial catalog.\nfunc DecodeAndValidate(raw []byte) ([]Entry, error) {\n\tdec := yaml.NewDecoder(bytes.NewReader(raw))\n\tdec.KnownFields(true)\n\tvar decoded []Entry\n\tif err := dec.Decode(&decoded); err != nil {\n\t\treturn nil, err\n\t}\n\tvar trailing any\n\tif err := dec.Decode(&trailing); err != io.EOF {\n\t\tif err == nil {\n\t\t\treturn nil, fmt.Errorf(\"multiple YAML documents are not allowed\")\n\t\t}\n\t\treturn nil, err\n\t}\n\tif len(decoded) == 0 {\n\t\treturn nil, fmt.Errorf(\"catalog is empty\")\n\t}\n\tseen := make(map[string]struct{}, len(decoded))\n\tfor i, entry := range decoded {\n\t\tlabel := fmt.Sprintf(\"entry %d\", i)\n\t\tif strings.TrimSpace(entry.Provider) == \"\" || strings.TrimSpace(entry.Model) == \"\" || strings.TrimSpace(entry.Region) == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"%s: provider, model, and region are required\", label)\n\t\t}\n\t\tif entry.Currency != \"USD\" {\n\t\t\treturn nil, fmt.Errorf(\"%s %s/%s: unsupported currency %q\", label, entry.Provider, entry.Model, entry.Currency)\n\t\t}\n\t\tif !cost.ValidPrice(entry.Pricing) {\n\t\t\treturn nil, fmt.Errorf(\"%s %s/%s: invalid pricing\", label, entry.Provider, entry.Model)\n\t\t}","sourceCodeStart":294,"sourceCodeEnd":330,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/2f49f0e1a352aa810e70056b7930aeb0b3d219b4/shared/platform/catalog/catalog.go#L294-L330","documentation":"Strict-parsing guard in DecodeAndValidate: a second YAML document followed the first in the catalog file. A catalog must be exactly one document so a plausible partial load can never happen; the file contents are at fault.","triggerScenarios":"Thrown at shared/platform/catalog/catalog.go:253 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Split multi-document YAML into a single document containing all entries","Remove accidental '---' separators that create extra documents","Regenerate the catalog with a serializer that emits one document"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"2f49f0e1a352aa810e70056b7930aeb0b3d219b4","analyzedAt":"2026-08-18T03:14:35.516Z","contentChangedAt":"2026-08-18T03:14:35.516Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}