go-delve/delve · error

internal debugger error: eval program finished without error

Error message

internal debugger error: eval program finished without error but %d call injections still active

What it means

run() executes the evalop program, suspending to run call-injection protocols when needed. When the program finishes without an error but stack.fncalls still holds active call injections, the debugger's internal state machine is inconsistent — every successful injection should have been retired. This is flagged as an internal debugger error because it indicates a bug in the call-injection protocol, not user error.

Source

Thrown at pkg/proc/eval.go:1032

	}
	stack.run()
}

func (stack *evalStack) run() {
	scope, curthread := stack.scope, stack.curthread
	for stack.opidx < len(stack.ops) && stack.err == nil {
		stack.callInjectionContinue = false
		stack.executeOp()
		// If the instruction we just executed requests the call injection
		// protocol by setting callInjectionContinue we switch to it.
		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()

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Report to go-delve/delve with the expression, Go version, and target platform — this indicates a debugger bug.
  2. Avoid function-call expressions in contexts that cannot support injection (coredump targets, some recordings); evaluate plain expressions instead.
  3. Update Delve; injection protocol bugs are frequently fixed across Go toolchain releases.
  4. Retry the operation in a live (non-recorded) debug session where the full injection protocol can execute.
Defensive patterns

Strategy: try-catch

Validate before calling

// before evaluating call expressions, ensure the target supports injection
if targetCoreDump || isRecording {
    return errors.New("function-call expressions are unsupported on this target type")
}

Type guard

func supportsCallInjection(t *proc.Target) bool { return t != nil && !t.IsCoreDump() }

Try / catch

_, err := scope.EvalExpression(expr, cfg)
if err != nil && strings.Contains(err.Error(), "call injections still active") {
    // treat as debugger bug: log expression+platform, restart the debug session
    log.Printf("injection leak on %q: %v", expr, err)
}

Prevention

When it happens

Trigger: An evalop program containing function-call operations (EvalExpression/SetVariable with function calls) completes with stack.err == nil while len(stack.fncalls) > 0 — i.e. the injected call never observed its completion breakpoint or the retirement path was skipped, so run() detects leftover active injections at the end.

Common situations: Injected call targets that never return normally (runtime exits, deadlocks, panics swallowed elsewhere); debugging targets where the call-injection completion event is missed (attached processes, coredumps, or recordings where injection cannot run); hitting this during record/replay (Record) where injections interact badly with the recorder.

Related errors


AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31). Data as JSON: /api/errors/71c59c0922c68bb1. Report an issue: GitHub.