go-delve/delve · error
could not find function at %#x
Error message
could not find function at %#x
What it means
Defer.EvalScope sets scope.PC to d.DwrapPC (the PC inside the deferred wrapper function) and resolves it to a function via PCToLine. If no function is found at that address, Delve refuses to build the scope since symbolization of the defer's target failed. Indicates stale or invalid DwrapPC, or missing symbol info.
Source
Thrown at pkg/proc/stack.go:1057
}
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 the
// CALL.
scope.Regs.CFA = (int64(d.variable.Addr) + d.variable.RealType.Common().ByteSize)
scope.Regs.Reg(scope.Regs.SPRegNum).Uint64Val = uint64(scope.Regs.CFA - int64(bi.Arch.PtrSize()))
} else {
// On architectures that have a link register CFA and SP have the same
// value but the address of the first argument is at CFA+ptrSize so we set
// CFA to the start of the argument frame minus one pointer size.
scope.Regs.CFA = int64(d.variable.Addr) + d.variable.RealType.Common().ByteSize - int64(bi.Arch.PtrSize())View on GitHub (pinned to a23773e6c3)
Solutions
- Verify the binary loaded in Delve exactly matches the running process (same build/paths)
- Re-attach or restart the debug session to refresh defer records
- Rebuild the target with full symbols
- Update Delve; defer/dwrap parsing changes across Go versions
Example fix
null
Defensive patterns
Strategy: validation
Validate before calling
fn := bi.PCToFunction(dwrapPC); if fn == nil { return errors.New("defer dwrap PC not in loaded binary: binary mismatch") } Type guard
func deferResolvable(bi *proc.BinaryInfo, d *proc.Defer) bool { fn, _, _ := bi.PCToLine(d.DwrapPC); return fn != nil } Try / catch
scope, err := d.EvalScope(t, thread); if err != nil && strings.Contains(err.Error(), "could not find function at") { /* flag binary/process mismatch and resync */ } Prevention
- Ensure Delve loads the exact binary the process executes
- Do not rebuild the binary while attached
- Keep Delve updated for Go-version-specific defer (dwrap) handling
- Validate defer chains look sane before scope evaluation
When it happens
Trigger: Calling Defer.EvalScope where d.DwrapPC doesn't map to any known function — defer records created by a different/older binary, corrupted _defer structs, or binary info loaded without the function containing DwrapPC (stripped/mismatched binary).
Common situations: Attached to a process running a different build than the binary Delve loaded; Go runtime version changes altering dwrap layout; corrupted memory reads of the defer chain.
Related errors
- could not get scope: %v
- could not find goroutine array
- channel filter without eval scope
- Frame %d only has %d deferred calls
- could not read DWARF function entry: %v
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/3f54ee28c58794f1.
Report an issue: GitHub.