sxyazi/yazi · error
Destination already exists
Error message
Destination already exists
What it means
bulk_rename refuses to overwrite: after computing the new URL, it checks maybe_exists(&new). If the destination already exists and must_identical does not confirm old and new are the same file, the pair fails with "Destination already exists". This prevents silent data loss from a rename collision.
Solutions
- Pick a unique destination name or add a suffix/number to avoid the collision.
- Delete or move the existing file at the destination first if the overwrite is intended.
- If the rename is intentional identity (same file), ensure old and new resolve to the same path so must_identical passes.
Example fix
// before
{ from: "a.txt", to: "b.txt" } // b.txt exists
// after
{ from: "a.txt", to: "b-2.txt" } Defensive patterns
Strategy: validation
Validate before calling
-- Lua, before bulk_rename
if Yo.fs_exists(new_url) then
ya.notify({ title = "Rename", content = "Destination exists: " .. new_url, level = "warn" })
return
end Prevention
- Generate unique names (append -1, -2, ...) when collisions are possible.
- Preview the rename mapping and highlight collisions before executing.
- Watch for case-only collisions on case-insensitive filesystems.
When it happens
Trigger: Renaming a file to a name that already exists in the same directory, where old and new are not the same inode.
Common situations: Regex/pattern rename producing a name that collides with another file; renaming a.txt to b.txt while b.txt exists; case-only renames on case-insensitive filesystems.
Related errors
- Failed to join new name with parent directory
- atime not available
- btime not available
- Cannot create file at root
- Cannot read cache stamp
AI-assisted analysis of sxyazi/yazi@8ebf930f17 (2026-09-02).
Data as JSON: /api/errors/38d8cd297064b543.
Report an issue: GitHub.
Appendix: source
Thrown at yazi-actor/src/mgr/bulk_rename.rs:126
return Ok(());
}
if !Self::ask_continue(&todo, decision)? {
return Ok(());
}
let permit = WATCHER.acquire().await.unwrap();
let (mut failed, mut succeeded) = (Vec::new(), HashMap::with_capacity(todo.len()));
for (o, n) in todo {
let (Ok(old), Ok(new)) =
(Self::replace_url(&selected[o.0], root, &o), Self::replace_url(&selected[n.0], root, &n))
else {
failed.push((o, n, anyhow!("Invalid new or old file name")));
continue;
};
if maybe_exists(&new).await && !engine::must_identical(&old, &new).await {
failed.push((o, n, anyhow!("Destination already exists")));
} else if let Err(e) = engine::rename(&old, &new).await {
failed.push((o, n, e.into()));
} else if let Ok(f) = engine::file(new).await {
succeeded.insert(old, f);
} else {
failed.push((o, n, anyhow!("Failed to retrieve file info")));
}
}
if !succeeded.is_empty() {
let it = succeeded.iter().map(|(o, n)| (o.as_url(), n.url.as_url()));
log_if_err!(Pubsub::pub_after_bulk_rename(it));
FilesOp::rename(succeeded);
}
drop(permit);
if !failed.is_empty() {
Self::output_failed(failed).await?;View on GitHub (pinned to 8ebf930f17)