go-delve/delve · error
could not continue existing thread %d %s
Error message
could not continue existing thread %d %s
What it means
Immediately after resuming the newly cloned thread, trapWaitInternal also resumes the parent thread (dbp.threads[int(wpid)]) that performed the clone. If that resume fails with an errno other than ESRCH, the wait loop aborts with this error identifying the parent pid and errno. Like error 586, ESRCH (thread vanished) is intentionally treated as benign.
Source
Thrown at pkg/proc/native/proc_linux.go:544
}
return nil, err
}
if halt {
th.os.running = false
dbp.threads[int(wpid)].os.running = false
return nil, nil
}
if err = th.resume(); err != nil {
if err == sys.ESRCH {
// thread died while we were adding it
delete(dbp.threads, th.ID)
continue
}
return nil, fmt.Errorf("could not continue new thread %d %s", cloned, err)
}
if err = dbp.threads[int(wpid)].resume(); err != nil {
if err != sys.ESRCH {
return nil, fmt.Errorf("could not continue existing thread %d %s", wpid, err)
}
}
continue
}
if status.StopSignal() == sys.SIGTRAP && (status.TrapCause() == sys.PTRACE_EVENT_EXEC) {
// A thread called exec and we now have a new process. Retrieve the
// thread ID of the exec'ing thread with PtraceGetEventMsg to remove it
// and create a new nativeProcess object to track the new process.
var tid uint
dbp.execPtraceFunc(func() { tid, err = sys.PtraceGetEventMsg(wpid) })
if err == nil {
delete(dbp.threads, int(tid))
}
dbp = newChildProcess(procgrp.procs[0], wpid)
dbp.followExec = true
cmdline, _ := dbp.initializeBasic()
tgt, err := procgrp.add(dbp, dbp.pid, dbp.memthread, findExecutable("", dbp.pid), proc.StopLaunched, cmdline)
if err != nil {View on GitHub (pinned to a23773e6c3)
Solutions
- Retry the session; this is usually a transient race between thread exit and resume.
- Check system logs (dmesg/journalctl) for OOM kills or SIGKILLs of the debuggee around the failure time.
- Verify ptrace permissions and absence of competing tracers on the target.
- Report to the delve project with the exact errno if consistently reproducible.
Defensive patterns
Strategy: retry
Validate before calling
// confirm target is not being killed externally ps -o pid,stat,cmd -p $PID dmesg | tail -20 | grep -i -E 'oom|killed'
Try / catch
if err != nil && strings.Contains(err.Error(), "could not continue existing thread") {
// parent thread may have raced with exit; check process state and retry
if processAlive(pid) { retrySession(pid) }
} Prevention
- Watch for OOM killer activity in dmesg when debugging memory-heavy targets
- Avoid environments that SIGKILL processes (health checkers, supervisors) during debugging
- Ensure no competing ptrace consumers are attached
- Retry transient failures; escalate to a bug report only when deterministic
When it happens
Trigger: The clone-parent thread is resumed via PTRACE_CONT and fails with a non-ESRCH errno — typically because the parent thread exited concurrently with an unexpected status, or the ptrace connection is broken.
Common situations: Programs where the spawning thread exits immediately after creating workers; debuggees killed externally (e.g. OOM killer) mid-clone; restricted ptrace environments (seccomp filters, sandboxed CI runners).
Related errors
- could not continue new thread %d %s
- could not get event message: %s
- process must be stopped in order to kill it
- error while waiting after adding process: %d %s
- ptraceGetLwpInfo err %s %d
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/973543473a6fee09.
Report an issue: GitHub.