{"record":{"id":"d49e827ebe7f7539","repo":"mikefarah/yq","slug":"cannot-encode-toml-entry-with-empty-path","errorCode":null,"errorMessage":"cannot encode TOML entry with empty path","messagePattern":"cannot encode TOML entry with empty path","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/yqlib/encoder_toml.go","lineNumber":160,"sourceCode":"\t\t}\n\t}\n\n\tfor i := 0; i < len(node.Content); i += 2 {\n\t\tkeyNode := node.Content[i]\n\t\tvalNode := node.Content[i+1]\n\t\tif !isTomlAttribute(valNode) {\n\t\t\tif err := te.encodeTopLevelEntry(w, []string{keyNode.Value}, valNode); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// encodeTopLevelEntry encodes a key/value at the root, dispatching to attribute, table, or array-of-tables\nfunc (te *tomlEncoder) encodeTopLevelEntry(w io.Writer, path []string, node *CandidateNode) error {\n\tif len(path) == 0 {\n\t\treturn fmt.Errorf(\"cannot encode TOML entry with empty path\")\n\t}\n\n\tswitch node.Kind {\n\tcase ScalarNode:\n\t\t// key = value\n\t\treturn te.writeAttribute(w, path[len(path)-1], node)\n\tcase SequenceNode:\n\t\t// Empty arrays should be encoded as [] attributes\n\t\tif len(node.Content) == 0 {\n\t\t\treturn te.writeArrayAttribute(w, path[len(path)-1], node)\n\t\t}\n\n\t\t// If all items are mappings => array of tables; else => array attribute\n\t\tallMaps := true\n\t\tfor _, it := range node.Content {\n\t\t\tif it.Kind != MappingNode {\n\t\t\t\tallMaps = false\n\t\t\t\tbreak","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/mikefarah/yq/blob/8b5af0694bb82b41d4ae180fac9972029066f90a/pkg/yqlib/encoder_toml.go#L142-L178","documentation":"encodeTopLevelEntry dispatches each root key to attribute/table/array-of-tables writers using the last path element as the key; an empty path means there is no key name to write, so it fails fast with this error. Normally unreachable via normal parsing (root map keys always produce paths), it surfaces via crafted/synthetic nodes or bugs.","triggerScenarios":"Encoding to `-o toml` a root mapping containing a key node whose path resolves empty — e.g. documents with empty-string keys collapsed by preprocessing, or synthetic nodes built by expressions before encodeRootMapping; called from encodeRootMapping (and reachable in tests like TestTomlEmptyPathPanic).","commonSituations":"Documents with empty YAML keys (`\"\": value`); programmatic use of yqlib where a path slice was built incorrectly; expressions that flatten away key names.","solutions":["Find and remove/normalize empty keys: `yq 'with_entries(select(key != \"\"))'` before `-o toml`.","Rename empty keys: `yq 'with_entries(.key = ((.key | select(. != \"\")) // \"root\"))'`.","If calling the library directly, verify the path passed to encodeTopLevelEntry is non-empty.","Preview keys with `yq 'keys' file.yaml` to spot empty-string keys."],"exampleFix":"# before\nyq -o toml '.' data.yaml   # data has \"\": value -> empty path\n\n# after\nyq -o toml 'with_entries(.key = ((.key | select(. != \"\")) // \"root\"))' data.yaml","handlingStrategy":"validation","validationCode":"yq 'keys | any(. == \"\")' file.yaml   # true means empty keys will break TOML","typeGuard":"hasEmptyKeys() { [ \"$(yq 'keys | any(. == \"\")' \"$1\")\" = \"true\" ]; }","tryCatchPattern":"yq -o toml '.' file.yaml || yq -o toml 'with_entries(.key = ((.key | select(. != \"\")) // \"root\"))' file.yaml","preventionTips":["Scan for empty-string keys before TOML output","Normalize empty keys with with_entries","When using the library API directly, assert len(path) > 0 before encodeTopLevelEntry"],"tags":["toml","encoder","path","empty-key"],"backgroundTag":"empty-key-path","analyzedSha":"8b5af0694bb82b41d4ae180fac9972029066f90a","analyzedAt":"2026-09-05T10:57:22.766Z","contentChangedAt":"2026-09-05T10:57:22.766Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}