rustdesk/rustdesk · error

[root-update] required installed plist is missing: {}

Error message

[root-update] required installed plist is missing: {}

What it means

The root-update flow requires the already-installed launchd plist to exist so it can be backed up and rewritten. `backup_update_plist` checks `symlink_metadata` and explicitly converts an `ErrorKind::NotFound` result into this bail, aborting the update rather than proceeding without a valid installed service definition.

Source

Thrown at src/platform/macos.rs:1033

}

pub fn update_to(_file: &str) -> ResultType<()> {
    let update_temp_dir = get_update_temp_dir_string();
    update_extracted(&update_temp_dir)?;
    Ok(())
}

fn backup_update_plist(source: &str, backup: &str) -> ResultType<()> {
    match std::fs::symlink_metadata(source) {
        Ok(metadata) => {
            if !metadata.file_type().is_file() {
                bail!("[root-update] plist is not a regular file: {}", source);
            }
            std::fs::copy(source, backup)?;
            Ok(())
        }
        Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
            bail!("[root-update] required installed plist is missing: {}", source)
        }
        Err(err) => Err(err.into()),
    }
}

fn validate_update_tree(path: &Path, framework_root: Option<&Path>) -> ResultType<()> {
    let metadata = std::fs::symlink_metadata(path)?;
    if metadata.file_type().is_symlink() {
        // Frameworks legitimately use internal symlinks (Resources,
        // Versions/Current), but never allow a link to leave its framework.
        let Some(framework_root) = framework_root else {
            bail!("[root-update] symlink outside framework: {}", path.display());
        };
        let target = std::fs::read_link(path)?;
        let target = if target.is_absolute() {
            target
        } else {
            path.parent().unwrap_or(Path::new("/")).join(target)

View on GitHub (pinned to 91c9fccbb0)

Solutions

  1. Install the service first: run `sudo /Applications/RustDesk.app/Contents/MacOS/RustDesk --install` so the plist is created, then update.
  2. Verify the expected plist exists: `ls /Library/LaunchAgents | grep -i rustdesk` (and /Library/LaunchDaemons).
  3. If upgrading from an old version, check for a renamed plist and install the new one instead of updating in place.
  4. Reinstall the app bundle entirely if the installation state is unclear.

Example fix

// before
sudo RustDesk --update   # fails: plist never installed
// after
sudo RustDesk --install --silent
sudo RustDesk --update
Defensive patterns

Strategy: try-catch

Validate before calling

let agent = format!("{}_server.plist", full_name);
let path = format!("/Library/LaunchAgents/{}", agent);
if !std::path::Path::new(&path).exists() {
    eprintln!("Service not installed; run --install first");
}

Type guard

fn plist_installed(full_name: &str) -> bool {
    std::path::Path::new(&format!("/Library/LaunchAgents/{}_server.plist", full_name)).exists()
}

Try / catch

match update_root() {
    Err(e) if e.to_string().contains("required installed plist is missing") => {
        eprintln!("RustDesk service not installed — running install first");
        install_service()?;
        update_root()?;
    }
    other => other,
}

Prevention

When it happens

Trigger: Running the privileged update (src/platform/macos.rs:1033) when the expected installed plist — such as /Library/LaunchAgents/{agent} or the root daemon plist referenced by the update routine — does not exist because RustDesk was never installed as a service or the plist was deleted.

Common situations: User downloaded a new build and ran --update without ever running the install step; manual cleanup (`launchctl unload` + rm) removed the plist; an OS reinstall or cleanup utility wiped /Library/LaunchAgents; plist name changed between RustDesk versions.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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