go-delve/delve · error

could not attach to %d

Error message

could not attach to %d

What it means

On macOS, attaching requires acquiring the target's mach task port via acquire_mach_task. If the mach call does not return KERN_SUCCESS, Delve cannot control the process and Attach fails with "could not attach to <pid>". This is the mach-level equivalent of a ptrace attach denial.

Source

Thrown at pkg/proc/native/proc_darwin.go:161

	return 0, proc.ErrWaitForNotImplemented
}

// Attach to an existing process with the given PID.
func Attach(pid int, waitFor *proc.WaitFor, _ []string) (*proc.TargetGroup, error) {
	if waitFor.Valid() {
		return nil, proc.ErrWaitForNotImplemented
	}
	if err := macutil.CheckRosetta(); err != nil {
		return nil, err
	}
	dbp := newProcess(pid)

	kret := C.acquire_mach_task(C.int(pid),
		&dbp.os.task, &dbp.os.portSet, &dbp.os.exceptionPort,
		&dbp.os.notificationPort)

	if kret != C.KERN_SUCCESS {
		return nil, fmt.Errorf("could not attach to %d", pid)
	}

	dbp.os.initialized = true

	var err error
	dbp.execPtraceFunc(func() { err = ptraceAttach(dbp.pid) })
	if err != nil {
		return nil, err
	}
	_, _, err = dbp.wait(dbp.pid, 0)
	if err != nil {
		return nil, err
	}

	tgt, err := dbp.initialize("", []string{})
	if err != nil {
		detachWithoutGroup(dbp, false)
		return nil, err

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Confirm the pid is correct and the process is still alive (ps -p <pid>).
  2. Ensure you own the target process; run dlv with sudo only if necessary.
  3. Enable developer mode (`sudo DevToolsSecurity -enable`) and make sure dlv is properly signed.
  4. Check the target isn't already debugged by another debugger (lldb, another dlv).
  5. Avoid attaching to SIP-protected system processes; re-launch a non-protected copy instead.

Example fix

// before
dlv attach 9999   // pid guessed, already dead
// after
ps aux | grep myapp
dlv attach $(pgrep -u $USER myapp)
Defensive patterns

Strategy: validation

Validate before calling

p, err := os.FindProcess(pid)
if err != nil {
    return err
}
if err := p.Signal(syscall.Signal(0)); err != nil {
    return fmt.Errorf("pid %d not attachable/alive: %w", pid, err)
}
// also ensure process owner matches current user (ps -o user -p pid)

Try / catch

tgt, err := proc.Attach(pid, [], logger)
if err != nil && strings.Contains(err.Error(), "could not attach to") {
    // check pid, ownership, SIP, and existing debugger before retrying
}

Prevention

When it happens

Trigger: Calling `dlv attach <pid>` (proc.Attach) on macOS when acquire_mach_task returns non-KERN_SUCCESS: wrong pid, process owned by another user, target already being debugged, or SIP protection.

Common situations: Attaching to a process started by another user or by launchd; attaching to a pid that already exited (race between finding the pid and attaching); attaching to system binaries protected by SIP; missing developer mode / codesign entitlements on the delve binary.

Related errors


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