go-delve/delve · error
internal debugger error: could not undo injected call during
Error message
internal debugger error: could not undo injected call during error recovery, original error: %v
What it means
When the eval program fails (stack.err != nil) with active call injections, run() must undo the injected calls before returning. If the topmost injection (fncall) is already the last retired call (stack.lastRetiredFncall), it cannot be undone safely, so the original error is replaced with this internal debugger error, preserving the original error as %v. It signals the undo path of the call-injection protocol hit an unrecoverable state.
Source
Thrown at pkg/proc/eval.go:1043
if stack.callInjectionContinue && stack.err == nil {
scope.callCtx.injectionThread = nil
return
}
}
if stack.err == nil && len(stack.fncalls) > 0 {
stack.err = fmt.Errorf("internal debugger error: eval program finished without error but %d call injections still active", len(stack.fncalls))
return
}
// If there is an error we must undo all currently executing call
// injections before returning.
if len(stack.fncalls) > 0 {
fncallLog("undoing calls (%v)", stack.err)
fncall := stack.fncallPeek()
if fncall == stack.lastRetiredFncall {
stack.err = fmt.Errorf("internal debugger error: could not undo injected call during error recovery, original error: %v", stack.err)
return
}
if fncall.undoInjection != nil {
if fncall.undoInjection.doComplete2 {
// doComplete2 is set if CallInjectionComplete{DoPinning: true} has been
// executed but CallInjectionComplete2 hasn't.
regs, err := curthread.Registers()
if err == nil {
callInjectionComplete2(scope, scope.BinInfo, fncall, regs, curthread)
}
} else {
// undoInjection is set if evalop.CallInjectionSetTarget has been
// executed but evalop.CallInjectionComplete hasn't, we must undo the callOP
// call in evalop.CallInjectionSetTarget before continuing.
switch scope.BinInfo.Arch.Name {
case "amd64":
regs, _ := curthread.Registers()
setSP(curthread, regs.SP()+uint64(scope.BinInfo.Arch.PtrSize()))View on GitHub (pinned to a23773e6c3)
Solutions
- Report to go-delve/delve including the original error text (embedded via %v) and the expression evaluated — the undo protocol hit an inconsistent state.
- Simplify the expression: split multi-call expressions into separate evaluations so a failure doesn't occur mid-injection-sequence.
- Re-evaluate in a fresh session/state; the target may be left in a partially-modified state after a failed undo.
- Update Delve and Go toolchain; injection undo bugs are toolchain-sensitive.
Defensive patterns
Strategy: try-catch
Validate before calling
// validate the whole expression compiles before running it
if _, err := evalop.Compile(lookup, expr, flags); err != nil {
return err // fail fast before any injection starts
} Try / catch
_, err := scope.EvalExpression(expr, cfg)
if err != nil && strings.Contains(err.Error(), "could not undo injected call") {
// target state may be dirty; re-attach or restart before further work
return fmt.Errorf("eval of %q left target in uncertain state: %w", expr, err)
} Prevention
- Split multi-call expressions into separate single-call evaluations
- Compile/validate expressions before executing to reduce mid-injection failures
- Avoid call expressions in recorded or unusual-attach sessions
- Re-attach or restart the session after any undo failure — state may be inconsistent
When it happens
Trigger: An error occurs mid-eval (bad expression after a call op, runtime error during injected call) while stack.fncalls is non-empty AND fncallPeek() == stack.lastRetiredFncall — i.e. the injection to undo was already retired, so undoing it would corrupt the target's state.
Common situations: Mixed expressions where a successful call injection is followed by a failing operation; errors during argument evaluation of a later call after an earlier one retired; recordings or attached sessions where undo breakpoints behave differently; Go runtime changes breaking injection undo semantics.
Related errors
- internal debugger error: eval program finished without error
- internal debugger error: wrong stack size at end %d
- unsupported pointer size %d
- expression %q is not a function
- could not find DIE for function %q
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/4c3275d7261edd99.
Report an issue: GitHub.