go-delve/delve · error
could not read auxiliary vector
Error message
could not read auxiliary vector: %v
What it means
nativeProcess.EntryPoint reads /proc/<pid>/auxv via os.ReadFile to locate the dynamic loader's entry point, which is required to debug PIE (position-independent) executables. If the auxv file cannot be read (e.g. the process has exited and /proc/<pid> is gone, or permission is denied), the error is wrapped and returned. Without auxv, Delve cannot compute the entry point and cannot properly initialize the debug session for PIE binaries.
Solutions
- Ensure the target process is still alive when attaching (use ps -p <pid> immediately before dlv attach).
- Fix permissions: run dlv as the same user as the target or with sufficient capabilities (CAP_SYS_PTRACE in containers).
- Lower /proc/sys/kernel/yama/ptrace_scope (e.g. echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope) if it blocks access.
- If using containers, launch with docker run --cap-add=SYS_PTRACE --security-opt seccomp=unconfined.
Example fix
// before: attach races with process exit
cmd.Start()
dlv.Attach(pid) // process may already be gone
// after: wait for readiness before attaching
cmd.Start()
for !portReady("127.0.0.1:4040") { time.Sleep(50 * time.Millisecond) }
dlv.Attach(pid) Defensive patterns
Strategy: validation
Validate before calling
// verify auxv readability before starting a PIE debug session
if _, err := os.ReadFile(fmt.Sprintf("/proc/%d/auxv", pid)); err != nil {
return fmt.Errorf("cannot access auxv for pid %d: %w", pid, err)
}
// also verify process is alive
if _, err := os.Stat(fmt.Sprintf("/proc/%d", pid)); err != nil {
return fmt.Errorf("process %d not running", pid)
} Try / catch
_, err := debugger.Attach(pid)
if err != nil && strings.Contains(err.Error(), "could not read auxiliary vector") {
// check whether the process died or permissions are insufficient
if _, statErr := os.Stat(fmt.Sprintf("/proc/%d/auxv", pid)); statErr != nil {
// process gone: restart it and re-attach
} else {
// permission problem: elevate capabilities or fix ptrace_scope
}
} Prevention
- Confirm the target process is alive before dlv attach
- Run dlv as the same user as the target, or add CAP_SYS_PTRACE in containers
- Avoid hidepid /proc mounts or run as root when they are required
- Set kernel.yama.ptrace_scope appropriately on hardened systems
When it happens
Trigger: Calling EntryPoint (internally during launch/attach initialization of a PIE binary) when /proc/<pid>/auxv cannot be opened: process already terminated, insufficient permissions, or the pid no longer exists.
Common situations: Attaching to a process that exits during startup; running dlv inside a container without CAP_SYS_PTRACE targeting a different user's process; hidepid mount option on /proc restricting visibility of other users' processes; kernel hardening (ptrace_scope=2/3).
Related errors
- Could not attach to pid
- Could not attach to pid
- could not read proc stat
- could not set options for new traced thread
- failed to remove memlock limit (try running with…
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/435b2f301963a1bd.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/proc/native/proc_linux.go:939
return nil
}
// For some reason the process will sometimes enter stopped state after a
// detach, this doesn't happen immediately either.
// We have to wait a bit here, then check if the main thread is stopped and
// SIGCONT it if it is.
time.Sleep(50 * time.Millisecond)
if s := status(dbp.pid, dbp.os.comm); s == 'T' {
_ = sys.Kill(dbp.pid, sys.SIGCONT)
}
return nil
}
// EntryPoint will return the process entry point address, useful for
// debugging PIEs.
func (dbp *nativeProcess) EntryPoint() (uint64, error) {
auxvbuf, err := os.ReadFile(fmt.Sprintf("/proc/%d/auxv", dbp.pid))
if err != nil {
return 0, fmt.Errorf("could not read auxiliary vector: %v", err)
}
return linutil.EntryPointFromAuxv(auxvbuf, dbp.bi.Arch.PtrSize()), nil
}
func (dbp *nativeProcess) SetUProbe(fnName string, goidOffset int64, args []ebpf.UProbeArgMap) error {
// Lazily load and initialize the BPF program upon request to set a uprobe.
if dbp.os.ebpf == nil {
var err error
dbp.os.ebpf, err = ebpf.LoadEBPFTracingProgram(dbp.bi.Images[0].Path)
if err != nil {
return err
}
}
// We only allow up to 12 args for a BPF probe.
// 6 inputs + 6 outputs.
// Return early if we have more.View on GitHub (pinned to a23773e6c3)