rustdesk/rustdesk · info

Connection manager window closed

Error message

Connection manager window closed

What it means

On Linux, if the connection manager window is closed, any tunnel spawned from it is also terminated: the select loop receives ipc::Data::CmWindowClosed and bails with this message. The design intent is that a tunnel must not outlive the cm window; the peer sees the drop and decides for itself.

Source

Thrown at src/server/connection.rs:1253

    ) -> ResultType<()> {
        let mut last_recv_time = Instant::now();
        if let Some(mut forward) = self.port_forward_socket.take() {
            log::info!("Running port forwarding loop");
            self.stream.set_raw();
            let mut hbbs_rx = crate::hbbs_http::sync::signal_receiver();
            loop {
                tokio::select! {
                    Some(data) = rx_from_cm.recv() => {
                        match data {
                            ipc::Data::Close => {
                                bail!("Close requested from connection manager");
                            }
                            // Same end as above: a tunnel must not outlive the window either.
                            // Only the reason differs, and a port forward carries none - the
                            // peer sees the tunnel drop and decides for itself.
                            #[cfg(target_os = "linux")]
                            ipc::Data::CmWindowClosed => {
                                bail!("Connection manager window closed");
                            }
                            ipc::Data::CmErr(e) => {
                                log::error!("Connection manager error: {e}");
                                bail!("{e}");
                            }
                            _ => {}
                        }
                    }
                    res = forward.next() => {
                        if let Some(res) = res {
                            last_recv_time = Instant::now();
                            self.stream.send_bytes(res?.into()).await?;
                        } else {
                            bail!("Forward reset by the peer");
                        }
                    },
                    res = self.stream.next() => {
                        if let Some(res) = res {

View on GitHub (pinned to 91c9fccbb0)

Solutions

  1. Keep the connection manager window open while tunnels are needed
  2. Re-establish the port forward after reopening the cm window
  3. If tunnels must survive window close, this requires a design change (currently intentional on Linux)
Defensive patterns

Strategy: try-catch

Validate before calling

// linux only: confirm cm window is still open before relying on a tunnel
#[cfg(target_os = "linux")]
if !cm_window_alive() {
    return Err(anyhow!("cm window closed; tunnel will be dropped"));
}

Try / catch

match tunnel_result {
    Err(e) if e.to_string() == "Connection manager window closed" => {
        log::info!("tunnel ended because cm window closed");
        // optionally re-establish after reopening cm
    }
    other => other,
}

Prevention

When it happens

Trigger: Linux only: the user closes the RustDesk connection manager window while a port-forward/tunnel is active, causing cm to notify child connections via Data::CmWindowClosed.

Common situations: Closing the cm window while a port forward is still in use; cm crash/window teardown on Linux desktop; session cleanup scripts closing the window.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of rustdesk/rustdesk@91c9fccbb0 (2026-09-10). Data as JSON: /api/errors/315f63b8b3f233eb. Report an issue: GitHub.