rustdesk/rustdesk · error
[root-update] Failed to download: {}
Error message
[root-update] Failed to download: {} What it means
The update .dmg is downloaded as root via a strict HTTP client from the allowlisted URL. If the server responds with a non-success HTTP status, the temp directory is removed and `check_update_as_root` bails with the status code. The update is aborted; the currently installed version keeps running.
Source
Thrown at src/updater.rs:629
let private_tmp = String::from_utf8(private_tmp_output.stdout)
.map_err(|err| hbb_common::anyhow::anyhow!("[root-update] mktemp output error: {}", err))?
.trim()
.to_owned();
if private_tmp.is_empty() {
bail!("[root-update] mktemp returned an empty download directory");
}
{
use std::os::unix::fs::PermissionsExt;
std::fs::set_permissions(&private_tmp, std::fs::Permissions::from_mode(0o700))?;
}
let filename = dmg_url.split('/').last().unwrap_or("rustdesk.dmg");
let file_path = std::path::PathBuf::from(format!("{}/{}", private_tmp, filename));
let tmp_path = file_path.to_string_lossy().to_string();
// Download
let mut response = client.get(&dmg_url).send()?;
if !response.status().is_success() {
let _ = std::fs::remove_dir_all(&private_tmp);
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.");View on GitHub (pinned to 91c9fccbb0)
Solutions
- Note the HTTP status in the message; a 404 means the dmg asset `rustdesk-<version>-<arch>.dmg` doesn't exist for that tag — verify the asset name on the release page.
- For 403/429, wait for the GitHub rate limit to reset or use a mirrored source.
- Check proxy/firewall rules allow reaching the release download host.
- Retry the update later; the updater will attempt again on its schedule.
Defensive patterns
Strategy: retry
Validate before calling
// pre-check that the release asset exists before triggering root update // curl -sIL '<dmg_url>' | head -1 -> expect HTTP/2 200
Try / catch
match check_update_as_root() {
Err(e) if e.to_string().contains("Failed to download") => {
log::warn!("update download failed, will retry later: {}", e);
// schedule retry with backoff
}
other => other,
} Prevention
- Verify the release tag has a matching rustdesk-<version>-<arch>.dmg asset before publishing updates.
- Ensure proxies/firewalls allow the release download host.
- Rely on the updater's retry schedule instead of immediate manual retries after 403/429.
When it happens
Trigger: `client.get(&dmg_url).send()` yields `response.status().is_success() == false` — e.g. 404 because the version tag has no matching release asset, 403/429 rate-limiting from GitHub, 5xx from the server, or a proxy returning an error page.
Common situations: GitHub release asset not yet published/renamed for the detected version; GitHub rate limiting; corporate proxy blocking github.com; captive portals returning HTML error pages with 4xx/5xx statuses.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- Failed to get content length: {}
- [root-update] Active session detected after extraction, defe
- [root-update] active session started before update launch
- TCP proxy error: {}
- Failed to get content length
AI-assisted analysis of rustdesk/rustdesk@91c9fccbb0 (2026-09-10).
Data as JSON: /api/errors/242a4566eff1ef98.
Report an issue: GitHub.