go-delve/delve · error
could not deliver signal:
Error message
could not deliver signal:
What it means
On macOS, kill() sends SIGKILL to the process group (-dbp.pid) via sys.Kill. If that kill syscall fails, the error is wrapped as 'could not deliver signal: <errno>'. This usually means the debugged task is already gone or the signal could not be delivered to the group.
Source
Thrown at pkg/proc/native/proc_darwin.go:191
return nil, err
}
tgt, err := dbp.initialize("", []string{})
if err != nil {
detachWithoutGroup(dbp, false)
return nil, err
}
return tgt, nil
}
// Kill kills the process.
func (procgrp *processGroup) kill(dbp *nativeProcess) (err error) {
if ok, _ := dbp.Valid(); !ok {
return nil
}
err = sys.Kill(-dbp.pid, sys.SIGKILL)
if err != nil {
return errors.New("could not deliver signal: " + err.Error())
}
for port := range dbp.threads {
if C.thread_resume(C.thread_act_t(port)) != C.KERN_SUCCESS {
return errors.New("could not resume task")
}
}
for {
var task C.task_t
port := C.mach_port_wait(dbp.os.portSet, &task, C.int(0))
if port == dbp.os.notificationPort {
break
}
}
dbp.postExit()
return
}
func (dbp *nativeProcess) requestManualStop() (err error) {View on GitHub (pinned to a23773e6c3)
Solutions
- Check whether the debuggee already exited (kill of a dead pid returns ESRCH) — treat as already-dead and continue detach
- Ensure dlv runs with sufficient privileges to signal the target (same user or proper entitlements)
- Re-run dlv and quit the session while the inferior is still alive
- If SIGKILL to the process group is failing, report upstream — the negative-pid group kill may need adjustment
Example fix
// before
err = sys.Kill(-dbp.pid, sys.SIGKILL)
if err != nil {
return errors.New("could not deliver signal: " + err.Error())
}
// after
err = sys.Kill(-dbp.pid, sys.SIGKILL)
if err != nil {
if errors.Is(err, syscall.ESRCH) {
return nil // process already gone
}
return fmt.Errorf("could not deliver SIGKILL to pid %d: %w", dbp.pid, err)
} Defensive patterns
Strategy: try-catch
Validate before calling
// check the target still exists before killing it
if err := syscall.Kill(pid, 0); err != nil {
// ESRCH: process already gone; skip the kill
return nil
} Try / catch
err := grp.kill(dbp)
if err != nil {
if strings.Contains(err.Error(), "could not deliver signal") {
if strings.Contains(err.Error(), "process already finished") || strings.Contains(err.Error(), "no such process") {
return nil // treat as success: target already dead
}
}
return err
} Prevention
- Run dlv as the same user (or with sufficient privileges) as the debuggee
- Quit debug sessions while the inferior is still alive to avoid racing its exit
- Treat ESRCH on kill as a no-op in teardown code
- Account for macOS SIP/entitlement constraints when signaling debugged tasks
When it happens
Trigger: Calling kill (detach after kill, or terminating a debug session) on macOS when sys.Kill(-pid, SIGKILL) fails — e.g. ESRCH because the process already exited, or EPERM due to privilege mismatch.
Common situations: Debuggee crashed or exited before dlv kills it; user pressed Ctrl-C/quit while the inferior was already dead; dlv running as a different user than the target; SIP restrictions interfering.
Related errors
- could not deliver signal
- can not run under Rosetta, check that the installed build of
- kinfo_getvmmap call failed
- could not resume task
- could not fork/exec
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/3d47ae74bdf793ae.
Report an issue: GitHub.