{"record":{"id":"cdb1a49b66f78cb7","repo":"go-delve/delve","slug":"frame-d-does-not-exist-in-goroutine-d","errorCode":null,"errorMessage":"Frame %d does not exist in goroutine %d","messagePattern":"Frame (.+?) does not exist in goroutine (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/proc/eval.go","lineNumber":115,"sourceCode":"\tif deferCall > 0 {\n\t\topts = StacktraceReadDefers\n\t}\n\n\tvar locs []Stackframe\n\tif g != nil {\n\t\tif g.Thread != nil {\n\t\t\tthreadID = g.Thread.ThreadID()\n\t\t}\n\t\tlocs, err = GoroutineStacktrace(dbp, g, frame+1, opts)\n\t} else {\n\t\tlocs, err = ThreadStacktrace(dbp, ct, frame+1)\n\t}\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif frame >= len(locs) {\n\t\treturn nil, fmt.Errorf(\"Frame %d does not exist in goroutine %d\", frame, gid)\n\t}\n\n\tif deferCall > 0 {\n\t\tif deferCall-1 >= len(locs[frame].Defers) {\n\t\t\treturn nil, fmt.Errorf(\"Frame %d only has %d deferred calls\", frame, len(locs[frame].Defers))\n\t\t}\n\n\t\td := locs[frame].Defers[deferCall-1]\n\t\tif d.Unreadable != nil {\n\t\t\treturn nil, d.Unreadable\n\t\t}\n\n\t\treturn d.EvalScope(dbp, ct)\n\t}\n\n\treturn FrameToScope(dbp, dbp.Memory(), g, threadID, locs[frame:]...), nil\n}\n","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/go-delve/delve/blob/a23773e6c31361e43246bc43a424ee009679b174/pkg/proc/eval.go#L97-L133","documentation":"ConvertEvalScope builds an EvalScope for a given goroutine ID and stack frame. After walking the goroutine's stack it checks whether the requested frame index actually exists; if the stack has fewer frames than the requested index, it refuses to build a scope and returns this error. It is a guard against out-of-range frame access, not a debugger malfunction.","triggerScenarios":"Calling ConvertEvalScope (directly or via pushLocal from service-level eval APIs, e.g. EvalExpression in a specific frame) with a frame index >= the number of frames in the target goroutine's stack; e.g. frame 5 on a goroutine whose stack only has 3 frames, or referencing a frame after the goroutine has exited and its stack shrunk.","commonSituations":"IDE/plugins caching a stale frame index after a step or breakpoint hit changed the stack depth; clients storing frame numbers across continuation events; goroutine that finished between listing and evaluation; asking for a deferred call frame on a shallow goroutine stack.","solutions":["Re-fetch the goroutine's stack (Stacktrace/GoroutineStacktrace) and use a frame index within len(locs)-1 before evaluating.","Re-acquire the current execution state: get a fresh stack after every stop event instead of reusing a stale frame index.","Check the goroutine still exists and is stopped (FindGoroutine/valid target) before evaluating in its frames.","For deferred-call scopes, pass deferCall > 0 only when the frame actually has pending defers."],"exampleFix":"// before\nscope, err := debugger.ConvertEvalScope(t, gid, 10, 0)\n// after\nlocs, err := proc.GoroutineStacktrace(t, g, 11, 0)\nif err != nil { return err }\nframe := 10\nif frame >= len(locs) { frame = len(locs) - 1 }\nscope, err := debugger.ConvertEvalScope(t, gid, frame, 0)","handlingStrategy":"validation","validationCode":"locs, err := proc.GoroutineStacktrace(t, g, frame+1, 0)\nif err != nil { return err }\nif frame < 0 || frame >= len(locs) {\n    return fmt.Errorf(\"frame %d unavailable, goroutine %d has %d frames\", frame, gid, len(locs))\n}","typeGuard":"func frameExists(locs []proc.Stackframe, frame int) bool { return frame >= 0 && frame < len(locs) }","tryCatchPattern":"scope, err := proc.ConvertEvalScope(t, gid, frame, 0)\nif err != nil {\n    if strings.Contains(err.Error(), \"does not exist in goroutine\") {\n        frame = 0 // fall back to topmost frame\n        scope, err = proc.ConvertEvalScope(t, gid, frame, 0)\n    }\n    if err != nil { return err }\n}","preventionTips":["Always fetch a fresh stacktrace after every stop event before referencing frame indices","Clamp frame indices to the current stack depth returned by Stacktrace","Never cache frame numbers across continue/step operations","Check goroutine status (running/dead) before evaluating in its frames"],"tags":["go","debugger","stack-frame","eval-scope"],"backgroundTag":"frame-out-of-range","analyzedSha":"a23773e6c31361e43246bc43a424ee009679b174","analyzedAt":"2026-08-31T15:12:45.221Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}