rustdesk/rustdesk · error

Failed to copy custom txt from {:?} to {:?}: {}

Error message

Failed to copy custom txt from {:?} to {:?}: {}

What it means

After creating the staging directory, the code copies the regular-file `custom.txt` with `std::fs::copy`. A failed copy aborts the update (with best-effort cleanup of the staging dir) and reports source, destination, and the underlying io::Error.

Source

Thrown at src/platform/windows.rs:3855

        if metadata.is_symlink() {
            allow_err!(remove_custom_client_staging_dir(&custom_client_staging_dir));
            bail!(
                "custom.txt at {:?} is a symlink, refusing to stage for security reasons.",
                src_path
            );
        }

        if metadata.is_file() {
            if !custom_client_staging_dir.exists() {
                if let Err(e) = std::fs::create_dir_all(custom_client_staging_dir) {
                    bail!("Failed to create parent directory {:?} when staging custom client files: {}", custom_client_staging_dir, e);
                }
            }
            let dst_path = custom_client_staging_dir.join("custom.txt");
            if let Err(e) = std::fs::copy(&src_path, &dst_path) {
                allow_err!(remove_custom_client_staging_dir(&custom_client_staging_dir));
                bail!(
                    "Failed to copy custom txt from {:?} to {:?}: {}",
                    src_path,
                    dst_path,
                    e
                );
            }
        } else {
            log::warn!(
                "custom.txt at {:?} is not a regular file, skipping.",
                src_path
            );
        }
    } else {
        log::info!("No custom txt found to stage for update.");
    }

    Ok(())
}

View on GitHub (pinned to 91c9fccbb0)

Solutions

  1. Retry the update after closing other RustDesk processes
  2. Free disk space if the io::Error indicates insufficient space
  3. Fix permissions on the staging directory (may require elevated delete + retry)
Defensive patterns

Strategy: retry

Validate before calling

if !src_path.is_file() { return; }
if !dst_dir_is_writable(&staging_dir) { /* fix ACLs first */ }
if free_disk_space(&staging_dir)? < src_len_plus_margin { /* free space first */ }

Try / catch

match std::fs::copy(&src_path, &dst_path) {
    Err(e) if e.kind() == std::io::ErrorKind::StorageFull => log::error!("disk full during staging"),
    Err(e) => log::warn!("copy failed ({e}); retry update"),
    Ok(_) => {}
}

Prevention

When it happens

Trigger: `std::fs::copy(&src_path, &dst_path)` returns `Err` — destination locked by another process, disk full, permission denied on the staging dir, or source unreadable at copy time.

Common situations: Another RustDesk instance holding `custom.txt` open in the staging dir; full system drive; ACL changes after a previous elevated run; AV interference during the update window.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


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