{"record":{"id":"c2f28b9289a4cc9a","repo":"mikefarah/yq","slug":"expected-mapping-node-for-block-body","errorCode":null,"errorMessage":"expected mapping node for block body","messagePattern":"expected mapping node for block body","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/yqlib/encoder_hcl.go","lineNumber":589,"sourceCode":"\t\t\tlabels := []string{childKey}\n\t\t\tif extraLabels, bodyNode, ok := extractBlockLabels(childVal); ok {\n\t\t\t\tlabels = append(labels, extraLabels...)\n\t\t\t\tchildVal = bodyNode\n\t\t\t}\n\t\t\tblock := body.AppendNewBlock(blockType, labels)\n\t\t\tif err := he.encodeNodeAttributes(block.Body(), childVal); err != nil {\n\t\t\t\treturn true, err\n\t\t\t}\n\t\t}\n\t}\n\n\treturn true, nil\n}\n\n// encodeNodeAttributes encodes the attributes of a mapping node (used for blocks)\nfunc (he *hclEncoder) encodeNodeAttributes(body *hclwrite.Body, node *CandidateNode) error {\n\tif node.Kind != MappingNode {\n\t\treturn fmt.Errorf(\"expected mapping node for block body\")\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 attribute for non-block 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":571,"sourceCodeEnd":607,"githubUrl":"https://github.com/mikefarah/yq/blob/8b5af0694bb82b41d4ae180fac9972029066f90a/pkg/yqlib/encoder_hcl.go#L571-L607","documentation":"When encoding HCL blocks, the body of a block must be a mapping of attributes/sub-blocks. This error is raised by encodeNodeAttributes (used by block and if-mapping encoding paths) when the node supplied as a block body is not a mapping, e.g. it is a scalar or sequence.","triggerScenarios":"Encoding HCL where a block's value is a non-map, e.g. `{resource: {aws_instance: \"oops\"}}` — the innermost block body is a scalar, so encodeNodeAttributes returns 'expected mapping node for block body'.","commonSituations":"Terraform-style YAML where a resource block accidentally holds a list instead of an object; typos in config where block names map to scalars; generated data with inconsistent nesting depth.","solutions":["Make the block body a mapping: `{resource: {aws_instance: {name: {...}}}}`","Fix the input data so every block level is an object of attribute name => value","Skip/reshape non-map entries with expressions like `del(.bad_block)` before `-o hcl`"],"exampleFix":"// before: {resource: {aws_instance: \"web\"}}\n// after:  {resource: {aws_instance: {web: {ami: \"ami-123\"}}}}","handlingStrategy":"validation","validationCode":"yq '[.. | tag] | any(\"!!seq\" or \"!!scalar\" at block positions)'  # or explicitly check each block:\nyq '.resource | to_entries | all(.value | type == \"!!map\")' input.yaml","typeGuard":"func blockBodiesAreMaps(root *CandidateNode) bool {\n  for i := 1; i < len(root.Content); i += 2 {\n    if root.Content[i].Kind != MappingNode { return false }\n  }\n  return true\n}","tryCatchPattern":"if err := he.encodeNodeAttributes(body, blockNode); err != nil {\n  if strings.Contains(err.Error(), \"expected mapping node for block body\") {\n    // reshape the block value into a mapping and retry\n  }\n}","preventionTips":["Every HCL block level must be an object: name => {attributes}","Validate nested block shapes with `to_entries | all(.value | type == \"!!map\")`","Fix inputs where blocks accidentally map to scalars or lists"],"tags":["hcl","encoding","blocks","mapping-required","yq"],"backgroundTag":"hcl-block-body-not-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"}