zed-industries/zed · error

Connection to TCP DAP timeout {address}

Error message

Connection to TCP DAP timeout {address}

What it means

In the TCP DAP transport, a select! races a timer (Duration::from_millis(self.timeout)) against a retry loop of TcpStream::connect(address); when the timer wins, this bail names the host:port that never accepted a connection. The inner loop retries connects with 100ms gaps and only exits early if the spawned process dies (see the 'exited before debugger attached' error).

Source

Thrown at crates/dap/src/transport.rs:606

        })
    }

    fn connect(
        &mut self,
    ) -> Task<
        Result<(
            Box<dyn AsyncWrite + Unpin + Send + 'static>,
            Box<dyn AsyncRead + Unpin + Send + 'static>,
        )>,
    > {
        let executor = self.executor.clone();
        let timeout = self.timeout;
        let address = SocketAddr::new(self.host, self.port);
        let process = self.process.clone();
        executor.clone().spawn(async move {
            select! {
                _ = executor.timer(Duration::from_millis(timeout)).fuse() => {
                    anyhow::bail!("Connection to TCP DAP timeout {address}");
                },
                result = executor.clone().spawn(async move {
                    loop {
                        match TcpStream::connect(address).await {
                            Ok(stream) => {
                                let (read, write) = stream.split();
                                return Ok((Box::new(write) as _, Box::new(read) as _))
                            },
                            Err(_) => {
                                let has_process = process.lock().is_some();
                                if has_process {
                                    let status = process.lock().as_mut().unwrap().try_status();
                                    if let Ok(Some(_)) = status {
                                        let child = process.lock().take().unwrap();
                                        let output = child.output().await?;
                                        let output = if output.stderr.is_empty() {
                                            String::from_utf8_lossy(&output.stdout).to_string()
                                        } else {

View on GitHub (pinned to f4178619ac)

Solutions

  1. Confirm the server actually listens: `ss -ltnp | grep <port>` / `nc -vz <host> <port>`
  2. Align host/port in the debug config with the server's --listen/--port arguments
  3. Increase the timeout setting if the server legitimately needs longer to bind
  4. Check firewall/NAT rules drop-vs-reject behavior between Zed and the target
Defensive patterns

Strategy: retry

Validate before calling

// Verify the port is listening before starting the TCP transport
let stream = smol::net::TcpStream::connect((host, port)).await;
anyhow::ensure!(stream.is_ok(), "nothing listening on {host}:{port} yet");

Try / catch

match connect_tcp(host, port, timeout_ms).await {
    Ok(io) => Ok(io),
    Err(err) if err.to_string().contains("Connection to TCP DAP timeout") => {
        // check whether the spawned process died, extend timeout, or surface a port-mismatch hint
        Err(err.context("verify the debug server listens on the configured host:port"))
    }
    Err(err) => Err(err),
}

Prevention

When it happens

Trigger: Attaching over TCP with host/port config where nothing listens: the debug server (e.g. 'debugpy -w', 'dlv --headless --listen', java agent) starts slowly and misses the window, the port is wrong or occupied by another service that rejects DAP, a firewall silently drops SYN packets so connects never complete (no RST means the loop keeps retrying until timeout).

Common situations: Port mismatch between adapter config and server args; server listening on 127.0.0.1 while config uses another interface; containerized debug servers not publishing the port; firewall/NAT dropping instead of refusing; timeout value too small for a slow-starting server.

Understand the failure class

Related errors


AI-assisted analysis of zed-industries/zed@f4178619ac (2026-08-20). Data as JSON: /api/errors/a930cc00eebbacdd. Report an issue: GitHub.