sxyazi/yazi · error · io::Error

restore target already exists: {to:?}

Error message

restore target already exists: {to:?}

What it means

`restore_item` (yazi-fs/src/trash/common.rs:12) puts a trashed item back by first creating a placeholder at the destination (`create_dir` for folders, `File::create_new` for files) and then renaming the backing file over it. If the destination already exists, both the create and the rename are refused and the caller gets `ErrorKind::AlreadyExists` with `restore target already exists: {to:?}`. This prevents silently overwriting whatever now lives at the original path.

Source

Thrown at yazi-fs/src/trash/common.rs:12

#[cfg(trash_unix)]
pub(super) fn restore_item(from: &std::path::Path, to: &std::path::Path) -> std::io::Result<()> {
	use std::{fs, io};

	let is_dir = fs::symlink_metadata(from)?.is_dir();
	if let Some(parent) = to.parent() {
		fs::create_dir_all(parent)?;
	}

	match if is_dir { fs::create_dir(to) } else { fs::File::create_new(to).map(|_| ()) } {
		Ok(()) => fs::rename(from, to),
		Err(e) if e.kind() == io::ErrorKind::AlreadyExists => Err(io::Error::new(
			io::ErrorKind::AlreadyExists,
			format!("restore target already exists: {to:?}"),
		)),
		Err(e) => Err(e),
	}
}

View on GitHub (pinned to 94abcfa92f)

Solutions

  1. Move or delete the file currently at the destination path shown in the message, then restore again.
  2. Restore to a different location instead of the original (manually move the backing file out of `~/.local/share/Trash/files/`).
  3. If you own the workflow, catch `AlreadyExists` and prompt the user to rename/overwrite instead of failing the whole batch.

Example fix

// before
trash::restore(entries)?; // fails whole batch if one target exists

// after
for entry in entries {
    if let Err(e) = restore_one(entry) {
        if e.kind() == io::ErrorKind::AlreadyExists {
            // skip and report, or restore under a new name
            continue;
        }
        return Err(e);
    }
}
Defensive patterns

Strategy: validation

Validate before calling

let exists = if is_dir { to.is_dir() } else { to.exists() };
if exists {
    // choose a new name or remove/move the occupant before restoring
}

Try / catch

match restore_item(&from, &to) {
    Ok(()) => {}
    Err(e) if e.kind() == io::ErrorKind::AlreadyExists => {
        // skip or prompt: rename occupant, or restore under a suffixed name
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Restoring a trash item whose original location has since been re-created: you trashed `report.pdf`, created a new file with the same name, then hit restore. Restoring two items to the same original path in one batch also triggers it.

Common situations: Trash restored long after deletion; a sync client (Dropbox/Nextcloud) recreated the path; duplicate items in the trash list with the same put-back path.

Related errors


AI-assisted analysis of sxyazi/yazi@94abcfa92f (2026-08-16). Data as JSON: /api/errors/4b67a0f2cbab9be4. Report an issue: GitHub.