{"record":{"id":"207b0729616e05f6","repo":"go-delve/delve","slug":"could-not-find-range-over-func-closure-parent-on-t","errorCode":null,"errorMessage":"could not find range-over-func closure parent on the stack","messagePattern":"could not find range-over-func closure parent on the stack","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/proc/stack.go","lineNumber":1301,"sourceCode":"\t\t\t\treturn false\n\t\t\t}\n\t\tcase lastFrameStage:\n\t\t\tframes = append(frames, fr)\n\t\t\tstage = doneStage\n\t\t\treturn false\n\t\tcase doneStage:\n\t\t\treturn false\n\t\t}\n\t\treturn true\n\t})\n\tif it.Err() != nil {\n\t\treturn nil, it.Err()\n\t}\n\tif nonMonotonicSP {\n\t\treturn nil, errors.New(\"corrupted stack (SP not monotonically decreasing)\")\n\t}\n\tif stage != doneStage {\n\t\treturn nil, errors.New(\"could not find range-over-func closure parent on the stack\")\n\t}\n\tif len(frames)%2 != 0 {\n\t\treturn nil, errors.New(\"incomplete range-over-func stacktrace\")\n\t}\n\tg.readDefers(frames)\n\treturn frames, nil\n}\n\ntype cachedStack struct {\n\tit     *stackIterator\n\tframes []Stackframe\n}\n\ntype stackCacheKey struct {\n\tgoid     int64\n\tthreadID int\n}\n","sourceCodeStart":1283,"sourceCodeEnd":1319,"githubUrl":"https://github.com/go-delve/delve/blob/a23773e6c31361e43246bc43a424ee009679b174/pkg/proc/stack.go#L1283-L1319","documentation":"rangeFuncStackTrace (pkg/proc/stack.go:1301) reconstructs the call chain of a range-over-func iterator by walking frames until it finds the parent function that contains the range statement (rangeParent). If the walk terminates without ever reaching the expected parent function (stage != doneStage), Delve concludes it cannot identify the range-over-func closure parent and returns this error instead of an inconsistent stack. This is a structural detection failure, not necessarily a corrupted stack.","triggerScenarios":"Raised by rangeFuncStackTrace (via setupRangeFrames, StepOut, next) when iterating stack frames no frame matches rangeParent.offset or the rangeParent chain, i.e.: (1) the topmost frame's function has no rangeParent recorded in its DWARF info (wrong or stale binary info); (2) the binary was recompiled after the debugger attached so function offsets in Delve's BinInfo no longer match; (3) the closure body exited the iterator loop normally and the stack contains only frames Delve cannot match (inlined/optimized frames missing closure pointers); (4) fr.Call.Fn == nil encountered at startStage ends the walk immediately with stage != doneStage.","commonSituations":"Using `next` or `stepout` while stopped inside a range-over-func yield closure; debugging a binary built with heavy optimization (-O, inlined closures) where the closure-to-parent relationship was optimized away; mixing binary versions (build once, recompile, debug old PID with dlv attach); supported-Go-version mismatch where Delve does not understand the newer compiler's closure encoding.","solutions":["Rebuild the binary without optimizations (-gcflags='all=-N -l') so closure metadata and rangeParent links survive, then restart the debug session.","Ensure the binary you are debugging matches the source: recompile and relaunch (dlv debug / dlv exec) rather than attaching to a stale binary.","Upgrade Delve to a version matching your Go release; range-over-func frame reconstruction depends on compiler-version-specific metadata.","Use `stack` (regular backtrace) instead of next/stepout to inspect the goroutine, avoiding the range-over-func reconstruction path.","If reproducible on current Delve + Go, report with a minimal reproducer and the debug log (--log-output=debug)."],"exampleFix":"// before: debugging an optimized binary, next inside the iterator body fails\n// with \"could not find range-over-func closure parent on the stack\"\ndlv exec ./app-opt\n\n// after: rebuild unoptimized and the parent frame is found\ngo build -gcflags=\"all=-N -l\" -o ./app\ndlv exec ./app","handlingStrategy":"fallback","validationCode":"// Before using next/stepout inside a closure, check the top frame is an expected\n// range-over-func body (unexported check; from client, verify the frame function\n// is a closure inside an iterator function rather than assuming parent lookup works).\nstate, _ := client.GetState()\ntopFn := state.CurrentThread.Function.Name()\n_ = topFn // if this is an optimized build, expect parent lookup to fail","typeGuard":null,"tryCatchPattern":"try {\n    frames = client.Stacktrace(goid, depth)\n} catch (err) {\n    if (strings.Contains(err.Error(), \"range-over-func closure parent\")) {\n        // fallback: plain backtrace without range-over-func reconstruction\n        frames = client.Stacktrace(goid, depth) // or use StacktraceSimple-equivalent\n    } else {\n        return err\n    }\n}","preventionTips":["Rebuild without optimizations before debugging range-over-func code","Never attach to a binary that has been recompiled since launch","Pin Delve and Go versions together in CI debug jobs","Prefer `stack` over next/stepout when stopped in iterator closures on old Delve"],"tags":["debugger","go","range-over-func","stack-unwinding"],"backgroundTag":"range-over-func-parent-not-found","analyzedSha":"a23773e6c31361e43246bc43a424ee009679b174","analyzedAt":"2026-08-31T15:12:45.221Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}