rustdesk/rustdesk · warning

[root-update] Active session started during download, deferr

Error message

[root-update] Active session started during download, deferring update.

What it means

Because the download as root can take minutes, `check_update_as_root` rechecks for active remote sessions via `has_no_active_conns_ipc()` right before installing. If a session has started during the download, the temp directory is cleaned up and this bail aborts the install so a user is not disconnected mid-session. This is an expected, intentional deferral rather than a fault.

Source

Thrown at src/updater.rs:647

        bail!("[root-update] Failed to download: {}", response.status());
    }
    // Create file exclusively (O_EXCL) and stream response directly into it
    {
        let mut file = std::fs::OpenOptions::new()
            .write(true)
            .create_new(true)
            .open(&file_path)
            .map_err(|e| { let _ = std::fs::remove_dir_all(&private_tmp); e })?;
        std::io::copy(&mut response, &mut file)
            .map_err(|e| { let _ = std::fs::remove_dir_all(&private_tmp); e })?;
    }
    log::info!("[root-update] Downloaded to {}", tmp_path);
    // Recheck active sessions before installing — download can take minutes
    if !has_no_active_conns_ipc() {
        if let Err(e) = std::fs::remove_dir_all(&private_tmp) {
            log::warn!("[root-update] Failed to remove temp dir {}: {}", private_tmp, e);
        }
        bail!("[root-update] Active session started during download, deferring update.");
    }
    // Install silently as root
    let result = crate::platform::update_from_dmg_as_root(&tmp_path, &version);
    // Clean up download directory
    if let Err(e) = std::fs::remove_dir_all(&private_tmp) {
        log::warn!("[root-update] Failed to remove temp dir {}: {}", private_tmp, e);
    }
    result.map(|_| true)
}

#[cfg(test)]
mod tests {
    use super::get_download_file_from_url;

    #[test]
    fn update_download_file_accepts_expected_github_asset_urls() {
        let file = get_download_file_from_url(
            "https://github.com/rustdesk/rustdesk/releases/download/1.4.0/rustdesk-1.4.0-x86_64.dmg",

View on GitHub (pinned to 91c9fccbb0)

Solutions

  1. No action needed — the update is deferred and will be retried on a later updater run.
  2. Ensure the machine is idle (no active RustDesk sessions) when an immediate update is required.
  3. Retry after all sessions have ended.
Defensive patterns

Strategy: fallback

Try / catch

// treat as benign deferral, not failure
if let Err(e) = check_update_as_root() {
    if e.to_string().contains("deferring update") {
        log::info!("update postponed until sessions end");
        return Ok(()); // expected path
    }
}

Prevention

When it happens

Trigger: An incoming remote connection/session starts between the initial check and the end of the dmg download, so `has_no_active_conns_ipc()` returns false at install time.

Common situations: Long downloads on slow networks overlapping with a legitimate user connecting to the machine; scheduled updates racing with working hours; unattended machines that suddenly receive connections.

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/6d6219a0d6ce380c. Report an issue: GitHub.