{"record":{"id":"382b1c352d78ae42","repo":"mikefarah/yq","slug":"collectobject-mismatching-node-sizes-are-you-cre","errorCode":null,"errorMessage":"CollectObject: mismatching node sizes; are you creating a map with mismatching key value pairs?","messagePattern":"CollectObject: mismatching node sizes; are you creating a map with mismatching key value pairs\\?","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/yqlib/operator_collect_object.go","lineNumber":39,"sourceCode":"\n\tcontext := originalContext.WritableClone()\n\n\tif context.MatchingNodes.Len() == 0 {\n\t\tcandidate := &CandidateNode{Kind: MappingNode, Tag: \"!!map\", Value: \"{}\"}\n\t\tlog.Debugf(\"collectObjectOperation - starting with empty map\")\n\t\treturn context.SingleChildContext(candidate), nil\n\t}\n\tfirst := context.MatchingNodes.Front().Value.(*CandidateNode)\n\tvar rotated = make([]*list.List, len(first.Content))\n\n\tfor i := 0; i < len(first.Content); i++ {\n\t\trotated[i] = list.New()\n\t}\n\n\tfor el := context.MatchingNodes.Front(); el != nil; el = el.Next() {\n\t\tcandidateNode := el.Value.(*CandidateNode)\n\t\tif len(candidateNode.Content) < len(first.Content) {\n\t\t\treturn Context{}, fmt.Errorf(\"CollectObject: mismatching node sizes; are you creating a map with mismatching key value pairs?\")\n\t\t}\n\n\t\tfor i := 0; i < len(first.Content); i++ {\n\t\t\tlog.Debugf(\"rotate[%v] = %v\", i, NodeToString(candidateNode.Content[i]))\n\t\t\tlog.Debugf(\"children:\\n%v\", NodeContentToString(candidateNode.Content[i], 0))\n\t\t\trotated[i].PushBack(candidateNode.Content[i])\n\t\t}\n\t}\n\tlog.Debugf(\"collectObjectOperation, length of rotated is %v\", len(rotated))\n\n\tnewObject := list.New()\n\tfor i := 0; i < len(first.Content); i++ {\n\t\tadditions, err := collect(d, context.ChildContext(list.New()), rotated[i])\n\t\tif err != nil {\n\t\t\treturn Context{}, err\n\t\t}\n\t\t// we should reset the parents and keys of these top level nodes,\n\t\t// as they are new","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/mikefarah/yq/blob/8b5af0694bb82b41d4ae180fac9972029066f90a/pkg/yqlib/operator_collect_object.go#L21-L57","documentation":"This error is thrown by collectObjectOperator, which implements yq's object construction (the `{...}` expression) by 'cross-multiplying' (rotating) the contents of all candidate nodes into new map entries. It uses the FIRST candidate node's content length as the expected number of key/value slots and requires every other candidate to have at least that many children. When a later candidate has fewer children than the first, the rotation arrays would be indexed beyond what that node provides, so yq aborts with this error instead of silently producing a malformed map.","triggerScenarios":"Running a `{...}` collect-object expression where the piped-in results are heterogeneous: e.g. `yq '.a[] | {key: .name}'`-style expressions where one result is a map with 2 entries and a later result is a scalar or 1-entry map, so len(candidateNode.Content) < len(first.Content). Specifically triggered when any node AFTER the first in context.MatchingNodes has fewer Content entries than the first node.","commonSituations":"Iterating over documents/entries where some items are missing fields (e.g. some YAML docs are empty or scalars instead of maps); passing an empty map `{}` node after a non-empty map into a collect; scripts that assume all input documents share the same schema; feeding mixed JSON/YAML inputs where nulls or short arrays sneak in.","solutions":["Inspect the input with `yq 'map(len)'` (or `.[] | length`) to find the node(s) with fewer entries than the first and fix or filter them out.","Filter out short/empty nodes before the collect: pipe through `select(length == N)` or `select(type == \"!!map\")` first.","Ensure each element you feed to `{...}` produces the same number of key/value pairs, e.g. by defaulting missing fields: `.name //= \"\"`.","Split the input into homogeneous groups and run a separate `{...}` collect per group instead of one over mixed data."],"exampleFix":"# before (fails when some docs are empty)\nyq '[.[] | {name: .name, port: .port}] | .[]' input.yaml\n# after (filter out docs without both fields)\nyq '[.[] | select(has(\"name\") and has(\"port\")) | {name: .name, port: .port}] | .[]' input.yaml","handlingStrategy":"validation","validationCode":"# validate all documents have the same number of entries before collecting:\nyq -e 'all(.[]; length == (.[0] | length))' input.yaml || echo \"heterogeneous input\"\n# or in a script:\nLEN=$(yq '.[0] | length' input.yaml)\nyq -e \"all(.[]; length == ${LEN})\" input.yaml","typeGuard":"// Go: guard before running a collect-object style rotation\nfunc uniformSize(nodes []*yqlib.CandidateNode) bool {\n    if len(nodes) == 0 { return true }\n    n := len(nodes[0].Content)\n    for _, nd := range nodes {\n        if len(nd.Content) < n { return false }\n    }\n    return true\n}","tryCatchPattern":null,"preventionTips":["Filter with select() so every node entering {...} has the same shape","Default missing fields before collecting (e.g. .name //= \"\")","Check node lengths with length per document before running the collect","Keep input documents schema-homogeneous; validate upstream"],"tags":["yq","collect-object","map-construction","mismatched-sizes"],"backgroundTag":"collect-object-mismatched-node-sizes","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"}