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

  1. Retry the session; this is usually a transient race between thread exit and resume.
  2. Check system logs (dmesg/journalctl) for OOM kills or SIGKILLs of the debuggee around the failure time.
  3. Verify ptrace permissions and absence of competing tracers on the target.
  4. 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

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


AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31). Data as JSON: /api/errors/973543473a6fee09. Report an issue: GitHub.