{"record":{"id":"6d6219a0d6ce380c","repo":"rustdesk/rustdesk","slug":"root-update-active-session-started-during-downlo","errorCode":null,"errorMessage":"[root-update] Active session started during download, deferring update.","messagePattern":"\\[root-update\\] Active session started during download, deferring update\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/updater.rs","lineNumber":647,"sourceCode":"        bail!(\"[root-update] Failed to download: {}\", response.status());\n    }\n    // Create file exclusively (O_EXCL) and stream response directly into it\n    {\n        let mut file = std::fs::OpenOptions::new()\n            .write(true)\n            .create_new(true)\n            .open(&file_path)\n            .map_err(|e| { let _ = std::fs::remove_dir_all(&private_tmp); e })?;\n        std::io::copy(&mut response, &mut file)\n            .map_err(|e| { let _ = std::fs::remove_dir_all(&private_tmp); e })?;\n    }\n    log::info!(\"[root-update] Downloaded to {}\", tmp_path);\n    // Recheck active sessions before installing — download can take minutes\n    if !has_no_active_conns_ipc() {\n        if let Err(e) = std::fs::remove_dir_all(&private_tmp) {\n            log::warn!(\"[root-update] Failed to remove temp dir {}: {}\", private_tmp, e);\n        }\n        bail!(\"[root-update] Active session started during download, deferring update.\");\n    }\n    // Install silently as root\n    let result = crate::platform::update_from_dmg_as_root(&tmp_path, &version);\n    // Clean up download directory\n    if let Err(e) = std::fs::remove_dir_all(&private_tmp) {\n        log::warn!(\"[root-update] Failed to remove temp dir {}: {}\", private_tmp, e);\n    }\n    result.map(|_| true)\n}\n\n#[cfg(test)]\nmod tests {\n    use super::get_download_file_from_url;\n\n    #[test]\n    fn update_download_file_accepts_expected_github_asset_urls() {\n        let file = get_download_file_from_url(\n            \"https://github.com/rustdesk/rustdesk/releases/download/1.4.0/rustdesk-1.4.0-x86_64.dmg\",","sourceCodeStart":629,"sourceCodeEnd":665,"githubUrl":"https://github.com/rustdesk/rustdesk/blob/91c9fccbb0f7bfe5f11644d5fbdec9b23fa10540/src/updater.rs#L629-L665","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["No action needed — the update is deferred and will be retried on a later updater run.","Ensure the machine is idle (no active RustDesk sessions) when an immediate update is required.","Retry after all sessions have ended."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"// treat as benign deferral, not failure\nif let Err(e) = check_update_as_root() {\n    if e.to_string().contains(\"deferring update\") {\n        log::info!(\"update postponed until sessions end\");\n        return Ok(()); // expected path\n    }\n}","preventionTips":["Schedule updates for idle windows on unattended machines.","Treat this message as expected behavior; do not alert on it.","Verify no active sessions exist before manually forcing an update."],"tags":["deferral","active-session","race-condition","macos","updater"],"backgroundTag":"invalid-state-transition","analyzedSha":"91c9fccbb0f7bfe5f11644d5fbdec9b23fa10540","analyzedAt":"2026-09-10T19:53:44.083Z","contentChangedAt":"2026-09-10T19:53:44.083Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}