helix-editor/helix · error · helix_dap::Error

Incorrect transport {}

Error message

Incorrect transport {}

What it means

Returned by helix_dap::Client::process when the (transport, port_arg) pair is unusable: transport must be "stdio" (port_arg ignored) or "tcp" with a port_arg. The match falls through to this error for any unknown transport string and also for "tcp" without a port_arg, since the arm requires ("tcp", Some(_)).

Source

Thrown at helix-dap/src/client.rs:68

}

impl Client {
    // Spawn a process and communicate with it by either TCP or stdio
    // The returned stream includes the Client ID so consumers can differentiate between multiple clients
    pub async fn process(
        transport: &str,
        command: &str,
        args: Vec<&str>,
        port_arg: Option<&str>,
        id: DebugAdapterId,
    ) -> Result<(Self, UnboundedReceiver<(DebugAdapterId, Payload)>)> {
        if command.is_empty() {
            return Result::Err(Error::Other(anyhow!("Command not provided")));
        }
        match (transport, port_arg) {
            ("tcp", Some(port_arg)) => Self::tcp_process(command, args, port_arg, id).await,
            ("stdio", _) => Self::stdio(command, args, id),
            _ => Result::Err(Error::Other(anyhow!("Incorrect transport {}", transport))),
        }
    }

    pub fn streams(
        rx: Box<dyn AsyncBufRead + Unpin + Send>,
        tx: Box<dyn AsyncWrite + Unpin + Send>,
        err: Option<Box<dyn AsyncBufRead + Unpin + Send>>,
        id: DebugAdapterId,
        process: Option<Child>,
    ) -> Result<(Self, UnboundedReceiver<(DebugAdapterId, Payload)>)> {
        let (server_rx, server_tx) = Transport::start(rx, tx, err, id);
        let (client_tx, client_rx) = unbounded_channel();

        let client = Self {
            id,
            _process: process,
            server_tx,
            request_counter: AtomicU64::new(0),

View on GitHub (pinned to 079a789e8c)

Solutions

  1. Use transport = "stdio" for adapters Helix spawns and talks to over stdin/stdout (most common) - no port-arg needed
  2. For TCP adapters, keep transport = "tcp" AND provide port-arg (the argument template used to pass the chosen port, e.g. "--port="); if port-arg is missing you get this same error
  3. Check spelling and case: the match is exact ("tcp"/"stdio", lowercase)
  4. Confirm the value is not inherited empty from a template variable

Example fix

# before
transport = "tcp"
# no port-arg -> Incorrect transport tcp

# after
transport = "tcp"
port-arg = "--port="
Defensive patterns

Strategy: validation

Validate before calling

fn transport_is_valid(transport: &str, port_arg: Option<&str>) -> bool {
    match transport {
        "stdio" => true,
        "tcp" => port_arg.is_some(),
        _ => false,
    }
}

Try / catch

// Client::process is async and returns Result; treat Error::Other with
// 'Incorrect transport' as a config bug, not a transient failure - do not retry:
if let Err(e) = dap::Client::process(...).await {
    if e.to_string().contains("Incorrect transport") { fix_debug_config(); }
}

Prevention

When it happens

Trigger: Debug config with transport = "ws", "pipe", or any string other than "tcp"/"stdio"; or transport = "tcp" but no port-arg field supplied, which fails the ("tcp", Some(port_arg)) arm and lands in the catch-all. Also a typo like "Stdio" (case-sensitive match).

Common situations: Adapter docs mention connecting over TCP and the user sets transport = "tcp" but forgets port-arg (e.g. port-arg = "--port="); copied a config written for a different client whose transport names differ; capitalization/whitespace typos in the transport value.

Related errors


AI-assisted analysis of helix-editor/helix@079a789e8c (2026-08-16). Data as JSON: /api/errors/0097927087534c14. Report an issue: GitHub.