go-delve/delve · error

ptrace

Error message

ptrace

What it means

In fork_exec, the child calls ptrace(PT_TRACE_ME, ...) so the parent debugger can trace it. Delve zeroes errno first because ptrace may legitimately return -1 on success; the perror/exit path only runs when the call actually failed. Seeing "ptrace" here means PT_TRACE_ME failed and the debuggee aborted before exec, so the launch fails.

Source

Thrown at pkg/proc/native/exec_darwin.c:79

	char sig;

	close(fd[1]);
	read(fd[0], &sig, 1);
	close(fd[0]);

	// Create a new process group.
	if (setpgid(0, 0) < 0) {
		perror("setpgid");
		exit(1);
	}

	// Set errno to zero before a call to ptrace.
	// It is documented that ptrace can return -1 even
	// for successful calls.
	errno = 0;
	pret = ptrace(PT_TRACE_ME, 0, 0, 0);
	if (pret != 0 && errno != 0) {
		perror("ptrace");
		exit(1);
	}

	// Change working directory if wd is not empty.
	if (wd && wd[0]) {
		errno = 0;
		cret = chdir(wd);
		if (cret != 0 && errno != 0) {
			char *error_msg;
			asprintf(&error_msg, "%s '%s'", "chdir", wd);
			perror(error_msg);
			exit(1);
		}
	}

	errno = 0;
	pret = ptrace(PT_SIGEXC, 0, 0, 0);
	if (pret != 0 && errno != 0) {

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Re-sign the dlv binary with a debugging entitlement (get-task-allow) or run `sudo DevToolsSecurity -enable` / `security authorizationdb` steps per delve docs.
  2. Confirm no other tracer is attached to the child; PT_TRACE_ME fails if the process is already traced.
  3. Rebuild/upgrade delve with the current Xcode toolchain so it matches your macOS version's ptrace semantics.
  4. On macOS, make sure you are on a developer build environment (codesign certificate installed; Developer Mode enabled) and that security software isn't denying ptrace.

Example fix

// before
pret = ptrace(PT_TRACE_ME, 0, 0, 0);
if (pret != 0 && errno != 0) { perror("ptrace"); exit(1); }
// after (diagnosis aid)
pret = ptrace(PT_TRACE_ME, 0, 0, 0);
if (pret != 0 && errno != 0) { fprintf(stderr, "ptrace PT_TRACE_ME: %s (errno=%d)\n", strerror(errno), errno); exit(1); }
Defensive patterns

Strategy: validation

Validate before calling

// Pre-flight on macOS: verify the dlv binary is entitled and codesigned for debugging
cmd := exec.Command("codesign", "-d", "--entitlements", "-", dlvPath)
out, err := cmd.Output()
if err != nil || !strings.Contains(string(out), "get-task-allow") {
	return fmt.Errorf("dlv binary lacks get-task-allow debugging entitlement; re-sign it")
}

Type guard

func isPtraceDenied(err error) bool {
	return err != nil && strings.Contains(err.Error(), "ptrace")
}

Try / catch

err := dlvClient.Launch(ctx, prog, args)
if err != nil && strings.Contains(err.Error(), "ptrace") {
	return fmt.Errorf("launch denied: re-sign dlv with get-task-allow / enable Developer Mode: %w", err)
}

Prevention

When it happens

Trigger: Launching a binary with the native backend on macOS when PT_TRACE_ME is rejected — most commonly a debugger-entitlement/macOS hardening issue, or when the process is already being traced.

Common situations: macOS 10.14+ requiring developer-mode entitlements and codesigning for debugging; dlv binary lacking get-task-allow entitlement; running under another debugger or hardened runtime; corporate security tools blocking ptrace.

Related errors


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