go-delve/delve · error
Could not attach to pid %d: this could be caused by a kernel
Error message
Could not attach to pid %d: this could be caused by a kernel security setting, try writing "0" to /proc/sys/kernel/yama/ptrace_scope
What it means
Specific EPERM diagnostic: the kernel Yama security module restricts ptrace to descendants, so attaching to an unrelated process fails with EPERM. The debugger reads /proc/sys/kernel/yama/ptrace_scope and, if it is non-zero, reports this as the likely cause.
Source
Thrown at service/debugger/debugger_linux.go:27
"syscall"
)
func init() {
attachErrorMessage = attachErrorMessageLinux
}
//lint:file-ignore ST1005 errors here can be capitalized
func attachErrorMessageLinux(pid int, err error) error {
fallbackerr := fmt.Errorf("could not attach to pid %d: %s", pid, err)
if serr, ok := err.(syscall.Errno); ok {
switch serr {
case syscall.EPERM:
// check if ptrace of non-child processes is disabled
bs, err := os.ReadFile("/proc/sys/kernel/yama/ptrace_scope")
if err == nil && len(bs) >= 1 && bs[0] != '0' {
// Yama documentation: https://www.kernel.org/doc/Documentation/security/Yama.txt
return fmt.Errorf("Could not attach to pid %d: this could be caused by a kernel security setting, try writing \"0\" to /proc/sys/kernel/yama/ptrace_scope", pid)
}
// check if the pid belongs to a different process
fi, err := os.Stat(fmt.Sprintf("/proc/%d", pid))
if err != nil {
return fallbackerr
}
if fi.Sys().(*syscall.Stat_t).Uid != uint32(os.Getuid()) {
return fmt.Errorf("Could not attach to pid %d: current user does not own the process", pid)
}
// check if the process is already being traced
statusfh, err := os.Open(fmt.Sprintf("/proc/%d/status", pid))
if err != nil {
return fallbackerr
}
defer statusfh.Close()
scan := bufio.NewScanner(statusfh)View on GitHub (pinned to a23773e6c3)
Solutions
- Write 0 to /proc/sys/kernel/yama/ptrace_scope: echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
- Launch the target as a child of delve (dlv debug / dlv exec) instead of attaching
- Attach as root (sudo dlv attach) which bypasses Yama restrictions
- Make the setting permanent via sysctl: kernel.yama.ptrace_scope=0
Example fix
// before dlv attach 12345 // fails with EPERM // after (shell) sudo sysctl -w kernel.yama.ptrace_scope=0 dlv attach 12345
Defensive patterns
Strategy: validation
Validate before calling
bs, _ := os.ReadFile("/proc/sys/kernel/yama/ptrace_scope")
yamaBlocked := len(bs) > 0 && bs[0] != '0' Try / catch
err := debugger.Attach(pid, []string{}, nil)
if err != nil && strings.Contains(err.Error(), "yama/ptrace_scope") {
// surface instruction to run: echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
} Prevention
- Set kernel.yama.ptrace_scope=0 in dev environments via sysctl
- Prefer dlv exec/debug (child process) over attach when Yama is on
- Document required privileges for attach workflows
- Use sudo dlv attach for cross-process debugging
When it happens
Trigger: 'dlv attach <pid>' or debugger.Attach on a process that is not a child of the debugger while /proc/sys/kernel/yama/ptrace_scope contains a value != '0'.
Common situations: Default Ubuntu/Debian kernels (ptrace_scope=1); CI containers with hardened settings; attaching to an already-running service started by another session.
Related errors
- failed to remove memlock limit (try running with CAP_SYS_RES
- could not set options for new traced thread %d %s
- could not read auxiliary vector: %v
- Could not attach to pid %d: current user does not own the pr
- no eBPF program loaded
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/6c9eb623e98e7567.
Report an issue: GitHub.