go-delve/delve · error
could not set options for new traced thread %d %s
Error message
could not set options for new traced thread %d %s
What it means
Delve attached to a new thread and consumed its initial stop, but the second PtraceSetOptions call (after the ESRCH recovery wait) failed with an error other than ESRCH. Without these options (PTRACE_O_TRACECLONE and optionally exec/fork tracing) the debugger cannot automatically track child threads, breaking thread and process follow behavior.
Source
Thrown at pkg/proc/native/proc_linux.go:383
if err != nil {
return nil, err
}
if status.Exited() {
return nil, fmt.Errorf("thread already exited %d", pid)
}
}
dbp.execPtraceFunc(func() { err = syscall.PtraceSetOptions(tid, ptraceOptions) })
if err == syscall.ESRCH {
if _, _, err = dbp.waitFast(tid); err != nil {
return nil, fmt.Errorf("error while waiting after adding thread: %d %s", tid, err)
}
dbp.execPtraceFunc(func() { err = syscall.PtraceSetOptions(tid, ptraceOptions) })
if err == syscall.ESRCH {
return nil, err
}
if err != nil {
return nil, fmt.Errorf("could not set options for new traced thread %d %s", tid, err)
}
}
dbp.threads[tid] = &nativeThread{
ID: tid,
dbp: dbp,
os: new(osSpecificDetails),
}
if dbp.memthread == nil {
dbp.memthread = dbp.threads[tid]
}
for _, bp := range dbp.Breakpoints().M {
if bp.WatchType != 0 {
err := dbp.threads[tid].writeHardwareBreakpoint(bp.Addr, bp.WatchType, bp.HWBreakIndex)
if err != nil {
return nil, err
}
}View on GitHub (pinned to a23773e6c3)
Solutions
- Run the debugger with elevated privileges (root or CAP_SYS_PTRACE) and confirm the container seccomp profile allows ptrace (Docker: --cap-add=SYS_PTRACE --security-opt seccomp=unconfined).
- Check kernel compatibility: gVisor/Kata containers may not support all PTRACE_O_* options; run on a standard kernel.
- Verify the thread's state via /proc/<pid>/task/<tid>/stat — threads stuck in D state can't respond to ptrace requests until they return to the run queue.
- Retry the debugger session; transient states usually clear.
Defensive patterns
Strategy: validation
Validate before calling
// check the environment supports ptrace options before launching
func ptraceEnvOK() error {
if os.Getenv("KUBERNETES_SERVICE_HOST") != "" {
if _, err := os.Stat("/proc/sys/kernel/yama/ptrace_scope"); err != nil {
return fmt.Errorf("check container seccomp profile allows ptrace")
}
}
if os.Geteuid() != 0 {
return fmt.Errorf("run with root or CAP_SYS_PTRACE for full ptrace option support")
}
return nil
} Type guard
func isSetOptionsErr(err error) bool {
return err != nil && strings.Contains(err.Error(), "could not set options for new traced thread")
} Try / catch
if err := startDebug(); err != nil {
if isSetOptionsErr(err) {
return fmt.Errorf("%w; ensure container has SYS_PTRACE and default seccomp profile is not blocking ptrace", err)
}
return err
} Prevention
- Run containers with --cap-add=SYS_PTRACE (Docker) or equivalent Kubernetes securityContext capabilities
- Avoid gVisor/Kata sandboxes for debugging workloads — their ptrace support is incomplete
- Confirm seccomp profiles permit ptrace syscalls
- Check target thread state in /proc — threads in D state may reject ptrace requests
When it happens
Trigger: addThread: after the ESRCH-retry path, syscall.PtraceSetOptions(tid, ptraceOptions) returns a non-ESRCH, non-nil error — e.g. EINVAL from invalid option combination on the kernel, EPERM from security restrictions, or EIO if the thread is in an unexpected state.
Common situations: Running on kernels/containers that restrict ptrace options (seccomp filters blocking ptrace); attaching to processes in uninterruptible states (D state) causing EIO; sandboxed CI environments (gVisor, some Docker seccomp profiles) with incomplete ptrace support.
Related errors
- Could not attach to pid %d: current user does not own the pr
- process must be stopped in order to kill it
- failed to remove memlock limit (try running with CAP_SYS_RES
- waiting for target execve failed: %s
- could not attach to new thread %d %s
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/9940f19c443ee3a1.
Report an issue: GitHub.