wezterm/wezterm · error

detach not implemented for RemoteSshDomain

Error message

detach not implemented for RemoteSshDomain

What it means

RemoteSshDomain (mux/src/ssh.rs:802) implements detach() as an unconditional bail because a wezterm-ssh domain has no detachable server-side session: attach is a no-op and detachable() deliberately returns false. Detach is only meaningful for domains backed by a persistent wezterm mux (unix/tls domains). Calling domain.detach() on an ssh domain — directly or via a detach action — hits this error.

Source

Thrown at mux/src/ssh.rs:802

    fn domain_id(&self) -> DomainId {
        self.id
    }

    fn domain_name(&self) -> &str {
        &self.name
    }

    async fn attach(&self, _window_id: Option<crate::WindowId>) -> anyhow::Result<()> {
        Ok(())
    }

    fn detachable(&self) -> bool {
        false
    }

    fn detach(&self) -> anyhow::Result<()> {
        bail!("detach not implemented for RemoteSshDomain");
    }

    fn state(&self) -> DomainState {
        // Just pretend that we are always attached, as we don't
        // have a defined attach operation that is distinct from
        // a spawn.
        DomainState::Attached
    }
}

#[derive(Debug)]
struct KillerInner {
    killer: Option<Box<dyn ChildKiller + Send + Sync>>,
    /// If we haven't populated `killer` by the time someone has called
    /// `kill`, then we use this to remember to kill as soon as we recv
    /// the child process.
    pending_kill: bool,
}

View on GitHub (pinned to 3ff7522b96)

Solutions

  1. Guard the call: only detach when domain.detachable() is true (ssh domains return false).
  2. Use the default domain-agnostic detach action, which targets the current domain only when it is detachable.
  3. In user code, treat detachable() == false as 'not an error, nothing to do' rather than calling detach().

Example fix

// before
if domain.domain_id() != *default_domain_id {
    domain.detach()?; // bails for RemoteSshDomain
}

// after
if domain.detachable() {
    domain.detach()?;
}
Defensive patterns

Strategy: validation

Validate before calling

if domain.detachable() {
    domain.detach()?;
} else {
    // ssh domains (RemoteSshDomain) are not detachable; this is not an error
    log::debug!("domain {} is not detachable; skipping", domain.domain_id());
}

Try / catch

match domain.detach() {
    Err(ref e) if e.to_string().contains("detach not implemented") => {
        // expected for ssh domains: ignore, nothing to detach
    }
    other => other?,
}

Prevention

When it happens

Trigger: A keybinding or CLI flow invoking DetachDomain/detach while the current domain is an ssh domain (wezterm ssh sessions, ssh_domains); generic code calling detach() without checking detachable().

Common situations: Config with a hardwired detach key used inside `wezterm ssh`; automation written against unix domains reused on ssh domains.

Related errors


AI-assisted analysis of wezterm/wezterm@3ff7522b96 (2026-08-20). Data as JSON: /api/errors/6bd0443da80ac397. Report an issue: GitHub.