mikefarah/yq · error
HCL encoder expects a mapping at the root level, got %v
Error message
HCL encoder expects a mapping at the root level, got %v
What it means
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'.
Source
Thrown at pkg/yqlib/encoder_hcl.go:495
// If all child values are mappings, treat each child key as a labelled instance of this block type
if handled, _ := he.encodeMappingChildrenAsBlocks(body, key, valueNode); handled {
return true
}
// No labels detected, render as unlabelled block
block := body.AppendNewBlock(key, nil)
if err := he.encodeNodeAttributes(block.Body(), valueNode); err == nil {
return true
}
return false
}
// encodeNode encodes a CandidateNode directly to HCL, preserving style information
func (he *hclEncoder) encodeNode(body *hclwrite.Body, node *CandidateNode) error {
if node.Kind != MappingNode {
return fmt.Errorf("HCL encoder expects a mapping at the root level, got %v", kindToString(node.Kind))
}
for i := 0; i < len(node.Content); i += 2 {
keyNode := node.Content[i]
valueNode := node.Content[i+1]
key := keyNode.Value
// Render as block or attribute depending on value type
if he.encodeBlockIfMapping(body, key, valueNode) {
continue
}
// Render as attribute: key = value
if err := he.encodeAttribute(body, key, valueNode); err != nil {
return err
}
}
return nilView on GitHub (pinned to 8b5af0694b)
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
Example fix
// before: yq -o hcl '.some_list'
// after: yq -o hcl '{block: .some_list}' Defensive patterns
Strategy: validation
Validate before calling
yq 'type == "!!map"' input.yaml # must print true before -o hcl
Type guard
func isHclEncodableRoot(node *CandidateNode) bool { return node.Kind == MappingNode } Try / catch
err := he.encodeNode(body, node)
if err != nil && strings.Contains(err.Error(), "expects a mapping at the root") {
// wrap the data in a top-level object and retry
} Prevention
- 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
When it happens
Trigger: `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).
Common situations: 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.
Related errors
- expected mapping node for block body
- csv encoding only works for arrays, got: %v
- failed to encode HCL: %w
- unsupported character %q in raw HCL expression
- HCL encoder does not support aliases
AI-assisted analysis of mikefarah/yq@8b5af0694b (2026-09-05).
Data as JSON: /api/errors/81c0570a4c6089de.
Report an issue: GitHub.