mikefarah/yq · error
csv object encoding only works for arrays of flat objects (s
Error message
csv object encoding only works for arrays of flat objects (string key => string/numbers/boolean value), child[0] is a %v
What it means
In CSV object-encoding mode, yq derives the CSV header from the keys of the first element, which must be a mapping (flat object). This error is thrown when the first child of the sequence is not a mapping, so no header can be extracted.
Source
Thrown at pkg/yqlib/encoder_csv.go:60
}
func (e *csvEncoder) encodeArrays(csvWriter *csv.Writer, content []*CandidateNode) error {
for i, child := range content {
if child.Kind != SequenceNode {
return fmt.Errorf("csv encoding only works for arrays of scalars (string/numbers/booleans), child[%v] is a %v", i, child.Tag)
}
err := e.encodeRow(csvWriter, child.Content)
if err != nil {
return err
}
}
return nil
}
func (e *csvEncoder) extractHeader(child *CandidateNode) ([]*CandidateNode, error) {
if child.Kind != MappingNode {
return nil, fmt.Errorf("csv object encoding only works for arrays of flat objects (string key => string/numbers/boolean value), child[0] is a %v", child.Tag)
}
mapKeys := getMapKeys(child)
return mapKeys.Content, nil
}
func (e *csvEncoder) createChildRow(child *CandidateNode, headers []*CandidateNode) []*CandidateNode {
childRow := make([]*CandidateNode, 0)
for _, header := range headers {
keyIndex := findKeyInMap(child, header)
value := createScalarNode(nil, "")
if keyIndex != -1 {
value = child.Content[keyIndex+1]
}
childRow = append(childRow, value)
}
return childRow
}View on GitHub (pinned to 8b5af0694b)
Solutions
- Ensure the root is an array of objects: `[{k1: v1, k2: v2}, ...]`
- Convert scalars to objects, e.g. `yq 'map({value: .})'` before encoding
- Use row mode by making elements arrays of scalars instead
Example fix
// before: yq -o csv '["a","b"]'
// after: yq -o csv '[{"name": "a"}, {"name": "b"}]' Defensive patterns
Strategy: type-guard
Validate before calling
yq 'if (.[0] | type) == "!!map" then "ok" else "not-object-array" end' input.yaml
Type guard
func isObjectArray(node *CandidateNode) bool {
return node.Kind == SequenceNode &&
len(node.Content) > 0 &&
node.Content[0].Kind == MappingNode
} Try / catch
out, err := encodeCSV(node)
if err != nil && strings.Contains(err.Error(), "csv object encoding only works") {
// fall back to wrapping data as array of objects or use JSON output
} Prevention
- Verify the first element is an object before object-CSV encoding
- Wrap scalars as objects with `map({value: .})` when needed
- Prefer JSON/YAML for heterogeneous arrays
When it happens
Trigger: `yq -o csv` on an array whose first element is a scalar or array instead of an object, e.g. `yq -o csv '["a","b"]'` or `[ [1,2], {a: 1} ]` — extractHeader sees child.Kind != MappingNode.
Common situations: Pointing yq at mixed-shape data; forgetting that object CSV mode requires an array of objects at the root; piping scalar lists where row mode (not object mode) was intended.
Related errors
- csv object encoding only works for arrays of flat objects (s
- csv encoding only works for arrays, got: %v
- failed to encode HCL: %w
- unsupported character %q in raw HCL expression
- HCL encoder expects a mapping at the root level, got %v
AI-assisted analysis of mikefarah/yq@8b5af0694b (2026-09-05).
Data as JSON: /api/errors/1cae2a6eb59e8d23.
Report an issue: GitHub.