go-delve/delve · error

stub exited while waiting for connection: %v

Error message

stub exited while waiting for connection: %v

What it means

When Delve launches a gdbserial-compatible stub (lldb, macOS debugserver, etc.) via Listen, it spawns the stub process and waits for its connection port before connecting. This error is returned when the stub process exits (reported via waitChan) before any connection could be established; the wrapped status contains the process exit status.

Source

Thrown at pkg/proc/gdbserial/gdbserver.go:304

	go func() {
		conn, _ := listener.Accept()
		acceptChan <- conn
	}()

	select {
	case conn := <-acceptChan:
		listener.Close()
		if conn == nil {
			return nil, errors.New("could not connect")
		}
		return p.Connect(conn, path, cmdline, pid, debugInfoDirs, stopReason)
	case status := <-p.waitChan:
		listener.Close()
		if err := checkRosettaExpensive(); err != nil {
			return nil, err
		}
		return nil, fmt.Errorf("stub exited while waiting for connection: %v", status)
	}
}

// Dial attempts to connect to the stub.
func (p *gdbProcess) Dial(addr string, path, cmdline string, pid int, debugInfoDirs []string, stopReason proc.StopReason) (*proc.TargetGroup, error) {
	for {
		conn, err := net.Dial("tcp", addr)
		if err == nil {
			return p.Connect(conn, path, cmdline, pid, debugInfoDirs, stopReason)
		}
		select {
		case status := <-p.waitChan:
			if err := checkRosettaExpensive(); err != nil {
				return nil, err
			}
			return nil, fmt.Errorf("stub exited while attempting to connect: %v", status)
		default:
		}

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Check the wrapped exit status in the message and run the stub manually to see its stderr (e.g. run the lldb-server/debugserver command directly).
  2. On macOS, verify debugserver is properly signed and has the required entitlements (DevToolsSecurity, get-task-allow).
  3. Verify the stub binary path/architecture matches the target (arm64 vs amd64, avoid Rosetta mismatches).
  4. Upgrade Delve and the stub (Xcode command line tools for debugserver) to compatible versions.
Defensive patterns

Strategy: validation

Validate before calling

cmd := exec.Command(stubPath, args...)
if err := cmd.Start(); err != nil {
    return fmt.Errorf("stub %s failed to start: %w", stubPath, err)
}
// ensure the stub process is alive before Listen
if cmd.ProcessState != nil {
    return fmt.Errorf("stub exited immediately; run it manually to see stderr")
}

Type guard

func stubAlive(p *os.Process) bool {
    return p != nil && p.Signal(syscall.Signal(0)) == nil
}

Try / catch

tg, err := dbg.Listen(...)
if err != nil && strings.Contains(err.Error(), "stub exited while waiting for connection") {
    return fmt.Errorf("debug stub failed at startup: %w (check entitlements/signing on macOS)", err)
}

Prevention

When it happens

Trigger: Calling debugger.Listen() with a gdbserial backend where the spawned stub (debugserver/lldb-server) dies before accepting the debugger's connection — bad stub path, missing entitlements, crash at startup, or unsupported platform (e.g. Rosetta issue caught by checkRosettaExpensive).

Common situations: macOS: debugserver lacking code-signing entitlements or blocked by SIP; wrong --init or headless configuration pointing at a nonexistent stub binary; stub killed by security software; running under Rosetta with incompatible stub/architecture.

Related errors


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