{"record":{"id":"81c0570a4c6089de","repo":"mikefarah/yq","slug":"hcl-encoder-expects-a-mapping-at-the-root-level-g","errorCode":null,"errorMessage":"HCL encoder expects a mapping at the root level, got %v","messagePattern":"HCL encoder expects a mapping at the root level, got (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/yqlib/encoder_hcl.go","lineNumber":495,"sourceCode":"\n\t// If all child values are mappings, treat each child key as a labelled instance of this block type\n\tif handled, _ := he.encodeMappingChildrenAsBlocks(body, key, valueNode); handled {\n\t\treturn true\n\t}\n\n\t// No labels detected, render as unlabelled block\n\tblock := body.AppendNewBlock(key, nil)\n\tif err := he.encodeNodeAttributes(block.Body(), valueNode); err == nil {\n\t\treturn true\n\t}\n\n\treturn false\n}\n\n// encodeNode encodes a CandidateNode directly to HCL, preserving style information\nfunc (he *hclEncoder) encodeNode(body *hclwrite.Body, node *CandidateNode) error {\n\tif node.Kind != MappingNode {\n\t\treturn fmt.Errorf(\"HCL encoder expects a mapping at the root level, got %v\", kindToString(node.Kind))\n\t}\n\n\tfor i := 0; i < len(node.Content); i += 2 {\n\t\tkeyNode := node.Content[i]\n\t\tvalueNode := node.Content[i+1]\n\t\tkey := keyNode.Value\n\n\t\t// Render as block or attribute depending on value type\n\t\tif he.encodeBlockIfMapping(body, key, valueNode) {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Render as attribute: key = value\n\t\tif err := he.encodeAttribute(body, key, valueNode); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil","sourceCodeStart":477,"sourceCodeEnd":513,"githubUrl":"https://github.com/mikefarah/yq/blob/8b5af0694bb82b41d4ae180fac9972029066f90a/pkg/yqlib/encoder_hcl.go#L477-L513","documentation":"The HCL format is structurally a set of blocks and attributes, so yq's HCL encoder requires the root node to be a mapping (object). Scalars or sequences at the root cannot be represented as HCL documents and trigger this error, which is then wrapped as 'failed to encode HCL'.","triggerScenarios":"`yq -o hcl '\"just a string\"'` or `yq -o hcl '[1,2,3]'` — encodeNode sees Kind != MappingNode at the root and returns this error via kindToString(node.Kind).","commonSituations":"Piping expressions that emit a single scalar/list into `-o hcl`; forgetting that HCL output needs `key: value` object shape at top level; converting JSON arrays of resources without wrapping them in a map.","solutions":["Ensure the root is an object: wrap with `{...}` or select a map, e.g. `yq -o hcl '{resource: .}'`","Rebuild the expression so it yields a mapping, e.g. `yq -o hcl '{\"my_block\": .}'`","Use JSON or YAML output for non-mapping data"],"exampleFix":"// before: yq -o hcl '.some_list'\n// after:  yq -o hcl '{block: .some_list}'","handlingStrategy":"validation","validationCode":"yq 'type == \"!!map\"' input.yaml   # must print true before -o hcl","typeGuard":"func isHclEncodableRoot(node *CandidateNode) bool { return node.Kind == MappingNode }","tryCatchPattern":"err := he.encodeNode(body, node)\nif err != nil && strings.Contains(err.Error(), \"expects a mapping at the root\") {\n    // wrap the data in a top-level object and retry\n}","preventionTips":["Wrap scalars/lists in `{key: ...}` before `-o hcl`","Verify the expression output is an object (`type == \"!!map\"`)","Remember HCL documents are blocks/attributes: root must be a map"],"tags":["hcl","encoding","root-node","mapping-required","yq"],"backgroundTag":"hcl-root-must-be-mapping","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"}