{"record":{"id":"f1b8eaf47b8e46c0","repo":"mikefarah/yq","slug":"index-v-out-of-range-array-size-is-v","errorCode":null,"errorMessage":"index [%v] out of range, array size is %v","messagePattern":"index \\[(.+?)\\] out of range, array size is (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/yqlib/operator_traverse_path.go","lineNumber":239,"sourceCode":"\t\tindexToUse := index\n\t\tcontentLength := len(node.Content)\n\t\tfor contentLength <= index {\n\t\t\tif contentLength == 0 {\n\t\t\t\t// default to nice yaml formatting\n\t\t\t\tnode.Style = 0\n\t\t\t}\n\n\t\t\tvalueNode := createScalarNode(nil, \"null\")\n\t\t\tnode.AddChild(valueNode)\n\t\t\tcontentLength = len(node.Content)\n\t\t}\n\n\t\tif indexToUse < 0 {\n\t\t\tindexToUse = contentLength + indexToUse\n\t\t}\n\n\t\tif indexToUse < 0 {\n\t\t\treturn nil, fmt.Errorf(\"index [%v] out of range, array size is %v\", index, contentLength)\n\t\t}\n\n\t\tnewMatches.PushBack(node.Content[indexToUse])\n\t}\n\treturn newMatches, nil\n}\n\nfunc keyMatches(key *CandidateNode, wantedKey string, exactKeyMatch bool) bool {\n\tif exactKeyMatch {\n\t\t// this is used for merge\n\t\treturn key.Value == wantedKey\n\t}\n\treturn matchKey(key.Value, wantedKey)\n}\n\nfunc traverseMap(context Context, matchingNode *CandidateNode, keyNode *CandidateNode, prefs traversePreferences, splat bool) (*list.List, error) {\n\tvar newMatches = orderedmap.NewOrderedMap()\n\terr := doTraverseMap(newMatches, matchingNode, keyNode.Value, prefs, splat)","sourceCodeStart":221,"sourceCodeEnd":257,"githubUrl":"https://github.com/mikefarah/yq/blob/8b5af0694bb82b41d4ae180fac9972029066f90a/pkg/yqlib/operator_traverse_path.go#L221-L257","documentation":"yq supports negative (from-the-end) indexing on arrays. After applying a negative offset, if the computed index is still below zero it means the requested position lies before the start of the array, so yq raises 'index out of range'. Positive indexes beyond the end are instead handled by padding/formatting logic, not this error.","triggerScenarios":"Traversing with an index like `.a[-10]` on an array whose length is smaller than the absolute offset, so contentLength + index < 0. E.g. array size 2 with index -5.","commonSituations":"Assuming jq-style clamping of out-of-range negative indexes, scripts computing offsets dynamically (e.g. `.[-$n]`) where n exceeds array length, or input arrays that shrank between yq versions/config runs.","solutions":["Clamp the index in your expression, e.g. `.a[-1]` for the last element instead of a large negative offset","Guard with a length check: `select(.a | length >= 3) | .a[-3]`","Use optional traverse semantics (`.[...]?`) so out-of-range paths yield nothing instead of an error","Fix the upstream data so the array actually contains the expected number of elements"],"exampleFix":"// before\nyq '.a[-10]' file.yaml\n// after\nyq '.a[-1]' file.yaml\n","handlingStrategy":"validation","validationCode":"// Guard negative index against array length before evaluating\nif idx < 0 && -idx > arrayLen {\n\treturn fmt.Errorf(\"index %d exceeds array length %d\", idx, arrayLen)\n}","typeGuard":"func indexInRange(idx, length int) bool { i := idx; if i < 0 { i += length }; return i >= 0 && i < length }","tryCatchPattern":"out, err := yqEval(\".a[-1]\", doc)\nif err != nil && strings.Contains(err.Error(), \"out of range\") {\n\t// treat as missing element and continue\n}","preventionTips":["Clamp negative indexes to array length before use","Prefer -1 for last element instead of computed large negative offsets","Add length checks with select() in the expression itself","Validate input array sizes when schemas change"],"tags":["yaml","array","indexing","out-of-range"],"backgroundTag":"index-out-of-range","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"}