{"record":{"id":"4b67a0f2cbab9be4","repo":"sxyazi/yazi","slug":"restore-target-already-exists-to","errorCode":null,"errorMessage":"restore target already exists: {to:?}","messagePattern":"restore target already exists: (.+?)","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"yazi-fs/src/trash/common.rs","lineNumber":12,"sourceCode":"#[cfg(trash_unix)]\npub(super) fn restore_item(from: &std::path::Path, to: &std::path::Path) -> std::io::Result<()> {\n\tuse std::{fs, io};\n\n\tlet is_dir = fs::symlink_metadata(from)?.is_dir();\n\tif let Some(parent) = to.parent() {\n\t\tfs::create_dir_all(parent)?;\n\t}\n\n\tmatch if is_dir { fs::create_dir(to) } else { fs::File::create_new(to).map(|_| ()) } {\n\t\tOk(()) => fs::rename(from, to),\n\t\tErr(e) if e.kind() == io::ErrorKind::AlreadyExists => Err(io::Error::new(\n\t\t\tio::ErrorKind::AlreadyExists,\n\t\t\tformat!(\"restore target already exists: {to:?}\"),\n\t\t)),\n\t\tErr(e) => Err(e),\n\t}\n}\n","sourceCodeStart":1,"sourceCodeEnd":19,"githubUrl":"https://github.com/sxyazi/yazi/blob/94abcfa92f4ad3f0a1aef6c1ea083cfb8aa6c8c2/yazi-fs/src/trash/common.rs#L1-L19","documentation":"`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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Move or delete the file currently at the destination path shown in the message, then restore again.","Restore to a different location instead of the original (manually move the backing file out of `~/.local/share/Trash/files/`).","If you own the workflow, catch `AlreadyExists` and prompt the user to rename/overwrite instead of failing the whole batch."],"exampleFix":"// before\ntrash::restore(entries)?; // fails whole batch if one target exists\n\n// after\nfor entry in entries {\n    if let Err(e) = restore_one(entry) {\n        if e.kind() == io::ErrorKind::AlreadyExists {\n            // skip and report, or restore under a new name\n            continue;\n        }\n        return Err(e);\n    }\n}","handlingStrategy":"validation","validationCode":"let exists = if is_dir { to.is_dir() } else { to.exists() };\nif exists {\n    // choose a new name or remove/move the occupant before restoring\n}","typeGuard":null,"tryCatchPattern":"match restore_item(&from, &to) {\n    Ok(()) => {}\n    Err(e) if e.kind() == io::ErrorKind::AlreadyExists => {\n        // skip or prompt: rename occupant, or restore under a suffixed name\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Check `to.exists()` before restoring and resolve collisions explicitly (skip / rename / ask).","Restore batches item-by-item so one collision cannot abort the rest.","After recreating a file you previously trashed, expect the old trash copy to collide on restore."],"tags":["trash","restore","already-exists","filesystem"],"backgroundTag":null,"analyzedSha":"94abcfa92f4ad3f0a1aef6c1ea083cfb8aa6c8c2","analyzedAt":"2026-08-16T09:56:24.836Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}