go-delve/delve · error
could not continue new thread %d %s
Error message
could not continue new thread %d %s
What it means
After adding a newly cloned thread (from a PTRACE_EVENT_CLONE/VFORK stop), trapWaitInternal calls th.resume() to let the new thread run. If resuming fails with an errno other than ESRCH (thread already died, which is silently tolerated), Delve aborts the wait loop with this error naming the cloned pid and the underlying errno. It signals the debugger could not return the new thread to execution during thread setup.
Source
Thrown at pkg/proc/native/proc_linux.go:540
if err == sys.ESRCH {
// thread died while we were adding it
delete(dbp.threads, int(cloned))
continue
}
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)View on GitHub (pinned to a23773e6c3)
Solutions
- Retry the debugging session — this is usually a transient race between thread creation and thread exit.
- Confirm ptrace permissions (yama ptrace_scope, CAP_SYS_PTRACE in containers).
- Ensure nothing else is sending signals to or tracing the new thread concurrently.
- If reproducible on a specific workload, capture the errno from the message and report it to the delve project.
Defensive patterns
Strategy: retry
Validate before calling
// check for external signal killers / competing tracers before session ps -o tracer= -p $PID cat /proc/sys/kernel/yama/ptrace_scope
Try / catch
if err != nil && strings.Contains(err.Error(), "could not continue new thread") {
// transient clone/resume race: retry the session after a short delay
time.Sleep(200 * time.Millisecond)
retrySession(pid)
} Prevention
- Attach to quiescent processes rather than ones spawning/terminating threads at high rate
- Do not SIGKILL individual threads of a debuggee during a session
- Run in environments without seccomp filters that block PTRACE_CONT
- Retry the session before investigating deeper — most failures are transient races
When it happens
Trigger: dbp.addThread(cloned) succeeds but th.resume() (which issues PTRACE_CONT via the backend) fails with EPERM, EIO, or similar non-ESRCH errno for the freshly cloned tid.
Common situations: Race where the new thread exits between addThread and resume but the exit status hasn't been reaped yet (yielding EIO/EPERM instead of ESRCH); ptrace restrictions in hardened containers; kernel version quirks around clone stops.
Related errors
- could not continue existing 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/face3f464807c9e2.
Report an issue: GitHub.