{"record":{"id":"1cae2a6eb59e8d23","repo":"mikefarah/yq","slug":"csv-object-encoding-only-works-for-arrays-of-flat","errorCode":null,"errorMessage":"csv object encoding only works for arrays of flat objects (string key => string/numbers/boolean value), child[0] is a %v","messagePattern":"csv object encoding only works for arrays of flat objects \\(string key => string/numbers/boolean value\\), child\\[0\\] is a (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/yqlib/encoder_csv.go","lineNumber":60,"sourceCode":"}\n\nfunc (e *csvEncoder) encodeArrays(csvWriter *csv.Writer, content []*CandidateNode) error {\n\tfor i, child := range content {\n\n\t\tif child.Kind != SequenceNode {\n\t\t\treturn fmt.Errorf(\"csv encoding only works for arrays of scalars (string/numbers/booleans), child[%v] is a %v\", i, child.Tag)\n\t\t}\n\t\terr := e.encodeRow(csvWriter, child.Content)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (e *csvEncoder) extractHeader(child *CandidateNode) ([]*CandidateNode, error) {\n\tif child.Kind != MappingNode {\n\t\treturn 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)\n\t}\n\tmapKeys := getMapKeys(child)\n\treturn mapKeys.Content, nil\n}\n\nfunc (e *csvEncoder) createChildRow(child *CandidateNode, headers []*CandidateNode) []*CandidateNode {\n\tchildRow := make([]*CandidateNode, 0)\n\tfor _, header := range headers {\n\t\tkeyIndex := findKeyInMap(child, header)\n\t\tvalue := createScalarNode(nil, \"\")\n\t\tif keyIndex != -1 {\n\t\t\tvalue = child.Content[keyIndex+1]\n\t\t}\n\t\tchildRow = append(childRow, value)\n\t}\n\treturn childRow\n\n}","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/mikefarah/yq/blob/8b5af0694bb82b41d4ae180fac9972029066f90a/pkg/yqlib/encoder_csv.go#L42-L78","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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.","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"],"exampleFix":"// before: yq -o csv '[\"a\",\"b\"]'\n// after:  yq -o csv '[{\"name\": \"a\"}, {\"name\": \"b\"}]'","handlingStrategy":"type-guard","validationCode":"yq 'if (.[0] | type) == \"!!map\" then \"ok\" else \"not-object-array\" end' input.yaml","typeGuard":"func isObjectArray(node *CandidateNode) bool {\n  return node.Kind == SequenceNode &&\n    len(node.Content) > 0 &&\n    node.Content[0].Kind == MappingNode\n}","tryCatchPattern":"out, err := encodeCSV(node)\nif err != nil && strings.Contains(err.Error(), \"csv object encoding only works\") {\n    // fall back to wrapping data as array of objects or use JSON output\n}","preventionTips":["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"],"tags":["csv","encoding","objects","yq"],"backgroundTag":"csv-nested-structure-unsupported","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"}