{"record":{"id":"bb1d02e683ff6a57","repo":"go-delve/delve","slug":"index-out-of-bounds","errorCode":null,"errorMessage":"index out of bounds","messagePattern":"index out of bounds","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/proc/eval.go","lineNumber":2859,"sourceCode":"\tif tt1, isslice1 := t1.(*godwarf.SliceType); isslice1 {\n\t\ttt2, isslice2 := t2.(*godwarf.SliceType)\n\t\tif !isslice2 {\n\t\t\treturn false\n\t\t}\n\t\treturn sameType(tt1.ElemType, tt2.ElemType)\n\t}\n\treturn t1.String() == t2.String()\n}\n\nfunc (v *Variable) sliceAccess(idx int) (*Variable, error) {\n\twrong := false\n\tif v.Flags&VariableCPtr == 0 {\n\t\twrong = idx < 0 || int64(idx) >= v.Len\n\t} else {\n\t\twrong = idx < 0\n\t}\n\tif wrong {\n\t\treturn nil, errors.New(\"index out of bounds\")\n\t}\n\tif v.loaded {\n\t\tif v.Kind == reflect.String {\n\t\t\ts := constant.StringVal(v.Value)\n\t\t\tif idx >= len(s) {\n\t\t\t\treturn nil, errors.New(\"index out of bounds\")\n\t\t\t}\n\t\t\tr := v.newVariable(\"\", v.Base+uint64(int64(idx)*v.stride), v.fieldType, v.mem)\n\t\t\tr.loaded = true\n\t\t\tr.Value = constant.MakeInt64(int64(s[idx]))\n\t\t\treturn r, nil\n\t\t} else {\n\t\t\tif idx >= len(v.Children) {\n\t\t\t\treturn nil, errors.New(\"index out of bounds\")\n\t\t\t}\n\t\t\treturn &v.Children[idx], nil\n\t\t}\n\t}","sourceCodeStart":2841,"sourceCodeEnd":2877,"githubUrl":"https://github.com/go-delve/delve/blob/a23773e6c31361e43246bc43a424ee009679b174/pkg/proc/eval.go#L2841-L2877","documentation":"Indexing (a[i]) into a string, array, or slice is bounds-checked by Delve's evaluator before reading debuggee memory. This throw site is the pre-load bounds check: for normal variables the index must satisfy 0 <= i < v.Len; for C pointers (VariableCPtr flag) only i >= 0 is enforced since there is no known length.","triggerScenarios":"Evaluating 'print s[10]' where s has Len <= 10 (string/slice/array), or a negative index like 'print a[-1]' on any indexable variable; also 'print p[5]' where p is a C pointer — only negative indexes fail here.","commonSituations":"Off-by-one errors while inspecting loops; using a loop variable that has already advanced past the end; indexing an empty slice/string (Len 0); mixing 0-based/1-based reasoning when poking at raw C pointers.","solutions":["Check the length first: 'print len(s)' or 'print len(a)', then use an index in [0, len)","If the variable shows an unexpectedly small Len, inspect why (is it empty? did you index the wrong variable?)","Use slice syntax to see available range, e.g. 'print s[0:5]' or 'print a[0:3]'","For C pointers, remember only negative indexes are rejected; bounds beyond the allocation are your responsibility"],"exampleFix":"// before (dlv CLI)\n(dlv) print s[10]        // len(s) == 5 -> error\n\n// after\n(dlv) print len(s)\n5\n(dlv) print s[4]","handlingStrategy":"validation","validationCode":"// before indexing in dlv\n(dlv) print len(s)   // confirm length, then index in [0, len)\n(dlv) print s[4]","typeGuard":"func safeIndex(idx int, length int64) bool {\n    return idx >= 0 && int64(idx) < length\n}","tryCatchPattern":"// RPC client pattern\nval, err := client.EvalVariable(scope, fmt.Sprintf(\"s[%d]\", i), cfg)\nif err != nil && strings.Contains(err.Error(), \"index out of bounds\") {\n    // query length and clamp/retry\n    lenVal, _ := client.EvalVariable(scope, \"len(s)\", cfg)\n    // recompute i within [0, len)\n}","preventionTips":["Always check len() in the debugger before indexing","Watch for loop variables that have advanced past the end when evaluating","Remember empty slices/strings reject index 0","For C pointers only negative indexes are checked — track your own bounds"],"tags":["go","debugger","index-out-of-range","bounds-check"],"backgroundTag":"index-out-of-bounds","analyzedSha":"a23773e6c31361e43246bc43a424ee009679b174","analyzedAt":"2026-08-31T15:12:45.221Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}