go-delve/delve · error
Process %d has exited with status %d
Error message
Process %d has exited with status %d
What it means
exitedToError converts an api.DebuggerState that reports Exited into an error, because most stepping commands (step, stepInstruction, next, stepout, call) cannot proceed on a dead process. When the RPC returns no error but state.Exited is true, Delve surfaces 'Process %d has exited with status %d' instead of returning a state that callers cannot act on.
Source
Thrown at pkg/terminal/command.go:1457
case "f", "c", "s":
return answer, nil
}
}
}
func scopePrefixSwitch(t *Term, ctx callContext) error {
if ctx.Scope.GoroutineID > 0 {
_, err := t.client.SwitchGoroutine(ctx.Scope.GoroutineID)
if err != nil {
return err
}
}
return nil
}
func exitedToError(state *api.DebuggerState, err error) (*api.DebuggerState, error) {
if err == nil && state.Exited {
return nil, fmt.Errorf("Process %d has exited with status %d", state.Pid, state.ExitStatus)
}
return state, err
}
func (c *Commands) step(t *Term, ctx callContext, args string) error {
if err := scopePrefixSwitch(t, ctx); err != nil {
return err
}
c.frame = 0
stepfn := t.client.Step
if ctx.Prefix == revPrefix {
stepfn = t.client.ReverseStep
}
state, err := exitedToError(stepfn())
if err != nil {
printcontextNoState(t)
return err
}View on GitHub (pinned to a23773e6c3)
Solutions
- Check state.Exited (or run `exitStatus`) before issuing further stepping commands.
- Restart the session (`restart` or relaunch) before continuing to debug.
- Set a breakpoint near program end if you need to inspect state before termination.
- Wrap scripted command sequences to stop on this error rather than continuing to step.
Example fix
// before
state, err := client.GetState()
// then blindly: cmd.step(...)
// after
state, err := client.GetState()
if err == nil && state.Exited {
fmt.Println("process already exited, restart first")
return
}
// then: cmd.step(...) Defensive patterns
Strategy: type-guard
Validate before calling
// Before stepping, confirm the process is still alive
state, err := client.GetState()
if err != nil {
return err
}
if state.Exited {
return fmt.Errorf("process %d already exited (status %d); restart before stepping", state.Pid, state.ExitStatus)
} Type guard
func processAlive(s *api.DebuggerState) bool {
return s != nil && !s.Exited
} Try / catch
state, err := cmd.step(...)
if err != nil && strings.Contains(err.Error(), "has exited with status") {
// recover: restart or stop the scripted session
fmt.Fprintln(os.Stderr, err)
return errStopSession
} Prevention
- Check state.Exited after every continue/step before issuing the next command.
- Use breakpoints near program end instead of stepping past termination.
- In scripted sessions, break the loop on any step error.
- Call `exitStatus`/inspect state after continue to detect termination early.
When it happens
Trigger: Any of step, next, stepout, stepInstruction, call executed after the debugged program has terminated (e.g. the program ran to completion or called os.Exit), so the returned state has Exited=true with ExitStatus set.
Common situations: Hitting Enter on `next` repeatedly until the program finishes, then stepping once more; a `call` expression terminates the process; scripted terminal sessions blindly issue step commands after the program exits.
Related errors
- command not available
- unknown config parameter
- illegal commandline '%s'
- redirect error: %s redirected twice
- failed to open file '%s': %w
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/b20b0ba6ea582497.
Report an issue: GitHub.