go-delve/delve · error
could not step out of %s: %v
Error message
could not step out of %s: %v
What it means
Delve steps the thread out of runtime.debugCallV2 to leave the debug-call machinery cleanly. This error wraps any failure from stepInstructionOut, meaning the thread could not be single-stepped out of the debug-call stub.
Source
Thrown at pkg/proc/fncall.go:873
case debugCallRegCompleteCall: // 0
p.fncallForG[callScope.g.ID].startThreadID = 0
case debugCallRegRestoreRegisters: // 16
// runtime requests that we restore the registers (all except pc and sp),
// this is also the last step of the function call protocol.
pc, sp := regs.PC(), regs.SP()
if err := thread.RestoreRegisters(fncall.savedRegs); err != nil {
fncall.err = fmt.Errorf("could not restore registers: %v", err)
}
if err := setPC(thread, pc); err != nil {
fncall.err = fmt.Errorf("could not restore PC: %v", err)
}
if err := setSP(thread, sp); err != nil {
fncall.err = fmt.Errorf("could not restore SP: %v", err)
}
fncallLog("stepping thread %d", thread.ThreadID())
if err := stepInstructionOut(callScope.callCtx.grp, p, thread, fncall.debugCallName, fncall.debugCallName); err != nil {
fncall.err = fmt.Errorf("could not step out of %s: %v", fncall.debugCallName, err)
}
if bi.Arch.Name == "amd64" {
// The tail of debugCallV2 corrupts the state of RFLAGS, we must restore
// it one extra time after stepping out of it.
// See https://github.com/go-delve/delve/issues/2985 and
// TestCallInjectionFlagCorruption
rflags := bi.Arch.RegistersToDwarfRegisters(0, fncall.savedRegs).Uint64Val(regnum.AMD64_Rflags)
err := thread.SetReg(regnum.AMD64_Rflags, op.DwarfRegisterFromUint64(rflags))
if err != nil {
fncall.err = fmt.Errorf("could not restore RFLAGS register: %v", err)
}
}
return true
case debugCallRegReadReturn: // 1
// read return arguments from stack
stack.callInjectionContinue = true
if fncall.panicvar != nil || fncall.err != nil {View on GitHub (pinned to a23773e6c3)
Solutions
- Clear other breakpoints on the debug-call frames or retry the call
- Ensure the Go version of the target is recent enough (debugCallV2, Go 1.14+)
- Restart the session if the thread is in an unknown state
- Upgrade Delve to pick up fixes for stepping-out regressions
Defensive patterns
Strategy: retry
Validate before calling
// Ensure a recent Go runtime (debugCallV2, Go 1.14+): // go version -m <binary> -> confirm go1.14 or newer
Try / catch
err := dbg.CallFunction(scope, fn, args)
if err != nil && strings.Contains(err.Error(), "could not step out") {
// clear other breakpoints, then retry once
}
Prevention
- Remove competing breakpoints near runtime.debugCallV2 before calling
- Require Go 1.14+ for call injection support
- Keep Delve current for step-out fixes
- Retry the call after a transient step failure
When it happens
Trigger: funcCallStep calls stepInstructionOut after restoring PC/SP and it returns an error (single-step breakpoint could not be set, thread stopped unexpectedly, step hit an unexpected breakpoint).
Common situations: Other breakpoints or watchpoints firing inside debugCallV2 while stepping out; process dying mid-step; concurrent modifications to breakpoints during the call; very old Go versions lacking debugCallV2 support.
Related errors
- not implemented: %s
- could not get precheck error reason: %v
- could not decode first frame
- unable to find function context
- unable to find locals: no debug information present in binar
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/4ec4b5abc82c8cfe.
Report an issue: GitHub.