zed-industries/zed · error

When using the `stdio` transport, the path to a debug adapte

Error message

When using the `stdio` transport, the path to a debug adapter binary must be set by Zed.

What it means

StdioTransport::start requires DebugAdapterBinary.command to be Some - the executable to spawn for the adapter. When a debug configuration selects the stdio transport but no command was resolved (user config gave none and Zed could not install/locate the adapter), this bail fires before any process is created. It is effectively an invariant: stdio transport without a binary path is unusable.

Source

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

            p.kill().log_err();
        }
    }
}

pub struct StdioTransport {
    process: Mutex<Child>,
    _stderr_task: Option<Task<()>>,
}

impl StdioTransport {
    // #[allow(dead_code, reason = "This is used in non test builds of Zed")]
    async fn start(
        binary: &DebugAdapterBinary,
        log_handlers: LogHandlers,
        cx: &mut AsyncApp,
    ) -> Result<Self> {
        let Some(binary_command) = &binary.command else {
            bail!(
                "When using the `stdio` transport, the path to a debug adapter binary must be set by Zed."
            );
        };
        let mut command = util::command::new_std_command(&binary_command);

        if let Some(cwd) = &binary.cwd {
            command.current_dir(cwd);
        }

        command.args(&binary.arguments);
        command.envs(&binary.envs);

        let mut process = Child::spawn(command, Stdio::piped(), Stdio::piped(), Stdio::piped())?;

        let _stderr_task = process.stderr.take().map(|stderr| {
            cx.background_spawn(TransportDelegate::handle_adapter_log(
                stderr,
                IoKind::StdErr,

View on GitHub (pinned to f4178619ac)

Solutions

  1. Set an explicit command (absolute path) plus arguments/envs in the adapter configuration so command is Some
  2. Fix the adapter name so Zed's built-in installer can fetch/locate the binary
  3. Pre-install the adapter and point the config at the installed executable
  4. If you meant to attach to an already-running server, use the tcp transport instead of stdio

Example fix

// before: stdio transport with no command
"debug": { "adapters": { "mytool": { "request": "launch" } } }

// after: give the stdio transport a concrete binary
"debug": {
  "adapters": {
    "mytool": {
      "command": "/usr/local/bin/mytool-dap",
      "args": ["--stdio"],
      "request": "launch"
    }
  }
}
Defensive patterns

Strategy: validation

Validate before calling

// Before building the transport, assert the invariant yourself
let command = binary
    .command
    .as_ref()
    .map(|c| c.to_string_lossy().into_owned())
    .with_context(|| format!("stdio transport requires a binary command; got binary {binary:?}"))?;

Type guard

fn has_stdio_command(binary: &DebugAdapterBinary) -> bool {
    binary.command.is_some()
}

Prevention

When it happens

Trigger: A debug adapter config declares transport 'stdio' while its Adapter implementation returned a DebugAdapterBinary with command: None - typically a custom adapter in Zed's debug settings that has neither an explicit command nor a Zed-managed install; or an adapter's install/resolution logic silently returned no binary.

Common situations: Hand-written adapter entries in Zed settings that set only host/port or nothing; adapter download failed earlier and left no cached binary; adapter name typo so no built-in implementation matches and command stays unset.

Related errors


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