{"record":{"id":"4c3275d7261edd99","repo":"go-delve/delve","slug":"internal-debugger-error-could-not-undo-injected-c","errorCode":null,"errorMessage":"internal debugger error: could not undo injected call during error recovery, original error: %v","messagePattern":"internal debugger error: could not undo injected call during error recovery, original error: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/proc/eval.go","lineNumber":1043,"sourceCode":"\t\tif stack.callInjectionContinue && stack.err == nil {\n\t\t\tscope.callCtx.injectionThread = nil\n\t\t\treturn\n\t\t}\n\t}\n\n\tif stack.err == nil && len(stack.fncalls) > 0 {\n\t\tstack.err = fmt.Errorf(\"internal debugger error: eval program finished without error but %d call injections still active\", len(stack.fncalls))\n\t\treturn\n\t}\n\n\t// If there is an error we must undo all currently executing call\n\t// injections before returning.\n\n\tif len(stack.fncalls) > 0 {\n\t\tfncallLog(\"undoing calls (%v)\", stack.err)\n\t\tfncall := stack.fncallPeek()\n\t\tif fncall == stack.lastRetiredFncall {\n\t\t\tstack.err = fmt.Errorf(\"internal debugger error: could not undo injected call during error recovery, original error: %v\", stack.err)\n\t\t\treturn\n\t\t}\n\t\tif fncall.undoInjection != nil {\n\t\t\tif fncall.undoInjection.doComplete2 {\n\t\t\t\t// doComplete2 is set if CallInjectionComplete{DoPinning: true} has been\n\t\t\t\t// executed but CallInjectionComplete2 hasn't.\n\t\t\t\tregs, err := curthread.Registers()\n\t\t\t\tif err == nil {\n\t\t\t\t\tcallInjectionComplete2(scope, scope.BinInfo, fncall, regs, curthread)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// undoInjection is set if evalop.CallInjectionSetTarget has been\n\t\t\t\t// executed but evalop.CallInjectionComplete hasn't, we must undo the callOP\n\t\t\t\t// call in evalop.CallInjectionSetTarget before continuing.\n\t\t\t\tswitch scope.BinInfo.Arch.Name {\n\t\t\t\tcase \"amd64\":\n\t\t\t\t\tregs, _ := curthread.Registers()\n\t\t\t\t\tsetSP(curthread, regs.SP()+uint64(scope.BinInfo.Arch.PtrSize()))","sourceCodeStart":1025,"sourceCodeEnd":1061,"githubUrl":"https://github.com/go-delve/delve/blob/a23773e6c31361e43246bc43a424ee009679b174/pkg/proc/eval.go#L1025-L1061","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// validate the whole expression compiles before running it\nif _, err := evalop.Compile(lookup, expr, flags); err != nil {\n    return err // fail fast before any injection starts\n}","typeGuard":null,"tryCatchPattern":"_, err := scope.EvalExpression(expr, cfg)\nif err != nil && strings.Contains(err.Error(), \"could not undo injected call\") {\n    // target state may be dirty; re-attach or restart before further work\n    return fmt.Errorf(\"eval of %q left target in uncertain state: %w\", expr, err)\n}","preventionTips":["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"],"tags":["go","debugger","call-injection","undo","internal-error"],"backgroundTag":"call-injection-undo-failed","analyzedSha":"a23773e6c31361e43246bc43a424ee009679b174","analyzedAt":"2026-08-31T15:12:45.221Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}