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
- Install the service first: run `sudo /Applications/RustDesk.app/Contents/MacOS/RustDesk --install` so the plist is created, then update.
- Verify the expected plist exists: `ls /Library/LaunchAgents | grep -i rustdesk` (and /Library/LaunchDaemons).
- If upgrading from an old version, check for a renamed plist and install the new one instead of updating in place.
- 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
- Always install the service (--install) before attempting an in-place update.
- Check /Library/LaunchAgents and /Library/LaunchDaemons for the plist before updating.
- Avoid cleanup tools that purge /Library/Launch* without reinstalling services.
- When migrating versions, verify whether the plist naming changed and install fresh instead of updating.
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
- [root-update] plist is not a regular file: {}
- daemon.plist not found in embedded resources
- Failed to read daemon.plist
- agent.plist not found in embedded resources
- Failed to read agent.plist
AI-assisted analysis of rustdesk/rustdesk@91c9fccbb0 (2026-09-10).
Data as JSON: /api/errors/5045ef10ba51a35f.
Report an issue: GitHub.