go-delve/delve · critical

waiting for target execve failed: %s

Error message

waiting for target execve failed: %s

What it means

During nativeProcess.Launch on Linux, delve forks/execs the target and waits for the child to stop at its first execve (PTRACE_TRACEME + exec). If dbp.wait returns an error while waiting for that execve stop, delve wraps it as 'waiting for target execve failed'. Launch cannot proceed because the child never reached a traceable state.

Source

Thrown at pkg/proc/native/proc_linux.go:132

			dbp.ctty, err = attachProcessToTTY(process, tty)
			if err != nil {
				return
			}
		}
		if wd != "" {
			process.Dir = wd
		}
		err = process.Start()
	})
	closefn()
	if err != nil {
		return nil, err
	}
	dbp.pid = process.Process.Pid
	dbp.childProcess = true
	_, _, err = dbp.wait(process.Process.Pid, 0)
	if err != nil {
		return nil, fmt.Errorf("waiting for target execve failed: %s", err)
	}
	tgt, err := dbp.initialize(cmd[0], debugInfoDirs)
	if err != nil {
		return nil, err
	}
	setupSharedLibBreakpoint(dbp, tgt)
	return tgt, nil
}

// Attach to an existing process with the given PID. Once attached, if
// the DWARF information cannot be found in the binary, Delve will look
// for external debug files in the directories passed in.
func Attach(pid int, waitFor *proc.WaitFor, debugInfoDirs []string) (*proc.TargetGroup, error) {
	if waitFor.Valid() {
		var err error
		pid, err = WaitFor(waitFor)
		if err != nil {
			return nil, err

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Run the target binary manually to confirm it starts: ./your-binary --help.
  2. Check kernel.yama.ptrace_scope (set to 0 or 1) and run delve as the same user or root.
  3. Retry the launch; single EINTR during wait is often transient.
  4. If the binary is setuid/setgid, remove those bits or launch via a non-setuid copy; ptrace of privileged children is blocked.
  5. Verify the command array's first element is a valid executable path.

Example fix

// before
cmd := []string{"./app", "--flag"} // app is setuid, launch fails

// after
// chmod u-s ./app  (remove setuid so ptrace is permitted)
cmd := []string{"/abs/path/app", "--flag"}
_ = debugger.Launch(cmd, "", false)
Defensive patterns

Strategy: validation

Validate before calling

// validate target and ptrace environment before Launch on Linux
func preflightLaunch(bin string) error {
    if fi, err := os.Stat(bin); err != nil || fi.IsDir() {
        return fmt.Errorf("binary %s not executable", bin)
    }
    if fi, _ := os.Stat(bin); fi.Mode()&(os.ModeSetuid|os.ModeSetgid) != 0 {
        return fmt.Errorf("remove setuid/setgid bits; ptrace of privileged children is blocked")
    }
    yama, _ := os.ReadFile("/proc/sys/kernel/yama/ptrace_scope")
    if s := strings.TrimSpace(string(yama)); s == "2" || s == "3" {
        return fmt.Errorf("kernel.yama.ptrace_scope=%s blocks launch; set to 0 or 1", s)
    }
    return nil
}

Try / catch

tgt, err := debugger.Launch(cmd, "", false)
if err != nil && strings.Contains(err.Error(), "waiting for target execve failed") {
    // child died before/at execve: run it standalone to see the real failure
    return fmt.Errorf("%w (run %q manually to see the exec error)", err, cmd[0])
}

Prevention

When it happens

Trigger: Calling debugger.Launch (dlv debug/exec) when the exec'd wait fails: the child crashed instantly after fork (e.g. exec binary missing despite pre-checks), was killed by a signal, or wait returned EINTR/ECHILD.

Common situations: Launching a binary that immediately segfaults; target binary with a bad interpreter shebang; exec'ing setuid binaries that drop traceability; seccomp/LSM policies (Yama ptrace_scope=2/3) blocking the child; disk/exec failures under sandboxed CI.

Related errors


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