go-delve/delve · error
could not get scope
Error message
could not get scope: %v
What it means
Defer.EvalScope builds an evaluation scope at the deferred call's argument frame. First it obtains a goroutine scope for the thread; if that underlying operation (thread registers, GetG, or stack access) fails, the error is wrapped with this prefix. The root cause is the inner error, not the defer itself.
Solutions
- Inspect the wrapped inner error (%v) for the real cause and address that
- Re-stop the process and re-fetch the goroutine before evaluating
- Avoid evaluating defer scopes while the goroutine is in runtime/systemstack code
- Update Delve if the inner error indicates a GetG or register-read bug
Example fix
null
Defensive patterns
Strategy: try-catch
Validate before calling
g, err := proc.GetG(thread); if err != nil || g == nil { return errors.New("cannot build defer scope: goroutine unavailable") } Try / catch
scope, err := deferVar.EvalScope(t, thread); if err != nil { var inner error; fmt.Sscanf(err.Error(), "could not get scope: %v", &inner); /* handle inner cause: re-stop, re-acquire goroutine */ } Prevention
- Evaluate defer scopes only while the target is consistently stopped
- Re-acquire goroutine state right before evaluation
- Avoid defer-scope evaluation during panics/runtime teardown
- Check the wrapped inner error before retrying
When it happens
Trigger: Calling Defer.EvalScope on a thread whose goroutine cannot be resolved or whose registers/stack can't be read — e.g. thread exited, target detached, or the goroutine is on the systemstack.
Common situations: Evaluating variables inside a deferred function while the debuggee is in an inconsistent state; inspecting a goroutine mid-panic where runtime state is torn down; races where the thread's goroutine changed between stop and evaluation.
Related errors
- could not find function at %#x
- channel filter without eval scope
- could not determine running goroutine for thread %#x…
- could not read DWARF function entry
- Frame only has deferred calls
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/1cc6007eb6d2cd1f.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/proc/stack.go:1049
d.link.Unreadable = errSPDecreased
}
return d.link
}
func (d *Defer) topdefer() *Defer {
if len(d.rangefunc) > 0 {
return d.rangefunc[0]
}
return d
}
// EvalScope returns an EvalScope relative to the argument frame of this deferred call.
// The argument frame of a deferred call is stored in memory immediately
// after the deferred header.
func (d *Defer) EvalScope(t *Target, thread Thread) (*EvalScope, error) {
scope, err := GoroutineScope(t, thread)
if err != nil {
return nil, fmt.Errorf("could not get scope: %v", err)
}
bi := thread.BinInfo()
scope.PC = d.DwrapPC
scope.File, scope.Line, scope.Fn = bi.PCToLine(d.DwrapPC)
if scope.Fn == nil {
return nil, fmt.Errorf("could not find function at %#x", d.DwrapPC)
}
// The arguments are stored immediately after the defer header struct, i.e.
// addr+sizeof(_defer).
if !bi.Arch.usesLR {
// On architectures that don't have a link register CFA is always the address of the first
// argument, that's what we use for the value of CFA.
// For SP we use CFA minus the size of one pointer because that would be
// the space occupied by pushing the return address on the stack during theView on GitHub (pinned to a23773e6c3)