go-delve/delve · error
could not resume task
Error message
could not resume task
What it means
After killing the task on macOS, kill() resumes all known thread ports with C.thread_resume. If any Mach thread_resume call does not return KERN_SUCCESS, 'could not resume task' is returned — a Mach port/thread state failure during teardown.
Source
Thrown at pkg/proc/native/proc_darwin.go:195
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) {
var (
task = C.mach_port_t(dbp.os.task)
thread = C.mach_port_t(dbp.memthread.os.threadAct)
exceptionPort = C.mach_port_t(dbp.os.exceptionPort)View on GitHub (pinned to a23773e6c3)
Solutions
- Verify the task is still valid before resuming threads; skip/ignore resume errors after SIGKILL since the task is being killed anyway
- Clear stale thread entries from dbp.threads when threads terminate during the session
- Ensure SIGKILL actually succeeded before resuming (check the preceding error)
- Report upstream if reproducible — teardown should tolerate KERN_TERMINATED/KERN_INVALID_RIGHT from thread_resume
Example fix
// before
for port := range dbp.threads {
if C.thread_resume(C.thread_act_t(port)) != C.KERN_SUCCESS {
return errors.New("could not resume task")
}
}
// after
for port := range dbp.threads {
if kr := C.thread_resume(C.thread_act_t(port)); kr != C.KERN_SUCCESS && kr != C.KERN_TERMINATED && kr != C.KERN_INVALID_RIGHT {
return fmt.Errorf("could not resume task: mach error %d", kr)
}
} Defensive patterns
Strategy: try-catch
Validate before calling
// verify the task is still alive before attempting per-thread resume
if err := syscall.Kill(pid, 0); err != nil {
// task already dead: skip thread_resume loop entirely
return nil
} Try / catch
err := grp.kill(dbp)
if err != nil && strings.Contains(err.Error(), "could not resume task") {
// after SIGKILL a failed thread_resume is usually harmless teardown noise
log.Println("non-fatal: thread_resume failed during kill", err)
err = nil
} Prevention
- Purge dead thread ports from the thread map when threads terminate
- Ignore resume failures on threads after a successful SIGKILL
- Check KERN_TERMINATED/KERN_INVALID_RIGHT as acceptable teardown results
- Keep SIGKILL and resume logic ordered so a dead task skips the resume loop
When it happens
Trigger: kill() iterating dbp.threads when a thread port is stale (thread already terminated), invalid, or the task is already dead, so thread_resume returns an error other than KERN_SUCCESS.
Common situations: Debuggee died between SIGKILL and the resume loop (stale thread ports in the map); thread terminated mid-session and its port became invalid; Mach port right revoked after task death.
Related errors
- could not attach to %d
- error while waiting for task
- could not follow task across exec: %d
- error waiting for thread stop %d
- could not set pc
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/7ea76f16cb1c098c.
Report an issue: GitHub.