go-delve/delve · error
terminated
Error message
terminated
What it means
During injected function-call evaluation, if the process exits (or terminates) while the call is in progress, the session detects it via processExited(state, err), emits exited/terminated events to the client, and then returns the sentinel error 'terminated' to the evaluate caller. It signals that the call never completed because the debuggee died.
Source
Thrown at service/dap/server.go:3403
loadCfg := s.loadConfig()
loadCfg.MaxStringLen = maxStringLenInCallRetVars
// TODO(polina): since call will resume execution of all goroutines,
// we should do this asynchronously and send a continued event to the
// editor, followed by a stop event when the call completes.
state, err := s.debugger.Command(&api.DebuggerCommand{
Name: api.Call,
ReturnInfoLoadConfig: api.LoadConfigFromProc(&loadCfg),
Expr: expr,
UnsafeCall: false,
GoroutineID: int64(goid),
WithEvents: true,
}, nil, s.conn.closedChan, s.convertDebuggerEvent)
if processExited(state, err) {
s.preTerminatedWG.Wait()
s.sendExitedEvent(state, err)
s.send(&dap.TerminatedEvent{Event: *s.newEvent("terminated")})
return nil, nil, errors.New("terminated")
}
if err != nil {
return nil, nil, err
}
// After the call is done, the goroutine where we injected the call should
// return to the original stopped line with return values. However,
// it is not guaranteed to be selected due to the possibility of the
// of simultaneous breakpoints. Therefore, we check all threads.
var retVars []*proc.Variable
found := false
for _, t := range state.Threads {
if t.GoroutineID == stateBeforeCall.SelectedGoroutine.ID &&
t.Line == stateBeforeCall.SelectedGoroutine.CurrentLoc.Line && t.CallReturn {
found = true
// The call completed. Get the return values.
retVars, err = s.debugger.FindThreadReturnValues(t.ID, loadCfg)
if err != nil {View on GitHub (pinned to a23773e6c3)
Solutions
- Do not evaluate calls that terminate the process (os.Exit, log.Fatal, panic)
- Re-launch the debuggee; the session is over once the process exits
- If calls near the end of main keep terminating, place breakpoints earlier or guard with runtime checks
- Inspect the call's side effects in a sandbox/test instead of evaluating them in the live target
Example fix
// before (debug console, terminates target)
os.Exit(1)
// after
fmt.Println("would exit") // or set a breakpoint instead of calling exit Defensive patterns
Strategy: try-catch
Validate before calling
// pre-screen dangerous calls before injecting
blocked := []string{"os.Exit", "log.Fatal", "panic"}
for _, b := range blocked {
if strings.HasPrefix(expr, b) { return fmt.Errorf("refusing %q", b) }
} Try / catch
if err.Error() == "terminated" {
// the debuggee exited: tear down the session and relaunch before any further requests
} Prevention
- Never evaluate process-terminating calls from the debug console
- Avoid injected calls near program exit points
- Treat a 'terminated' result as final — re-launch to continue debugging
When it happens
Trigger: The injected call causes the target process to exit (e.g. calling os.Exit or a function that panics fatally); the debuggee is killed externally during a call; the program finishes/naturally exits while a call is being injected at the end of main.
Common situations: Evaluating calls like os.Exit(1) or log.Fatal from the debug console; long-running call racing with program termination at the last breakpoint in main; crashes triggered by the injected call's side effects.
Related errors
- call is only supported with topmost stack frame
- call stopped
- function calls not allowed without using 'call'
- literal can not be allocated because function calls are not
- function calls not supported by this version of Go
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/8b113f70c6ad21b1.
Report an issue: GitHub.