clash-verge-rev/clash-verge-rev · error
Backup file already exists: {file_name}
Error message
Backup file already exists: {file_name} What it means
import_local_backup computes the target path inside the local backup directory and checks if it already exists. If a file with the same name is already present, the import is rejected to avoid silent overwrite. The check runs after the same-path short-circuit, so it only fires for genuinely conflicting copies.
Source
Thrown at src-tauri/src/feat/backup.rs:214
let file_name = source_path
.file_name()
.and_then(|name| name.to_str())
.ok_or_else(|| anyhow!("Invalid backup file name"))?;
let backup_dir = local_backup_dir()?;
let target_path = backup_dir.join(file_name);
if target_path == source_path {
// Already located in the backup directory
return Ok(file_name.to_string().into());
}
if let Some(parent) = target_path.parent() {
fs::create_dir_all(parent).await?;
}
if target_path.exists() {
return Err(anyhow!("Backup file already exists: {file_name}"));
}
fs::copy(&source_path, &target_path)
.await
.map_err(|err| anyhow!("Failed to import backup file: {err:#?}"))?;
Ok(file_name.to_string().into())
}
async fn move_file(from: PathBuf, to: PathBuf) -> Result<()> {
if let Some(parent) = to.parent() {
fs::create_dir_all(parent).await?;
}
match fs::rename(&from, &to).await {
Ok(_) => Ok(()),
Err(rename_err) => {
// Attempt copy + remove as fallback, covering cross-device movesView on GitHub (pinned to 5cad0f2799)
Solutions
- Delete or rename the existing local backup before re-importing.
- Offer the user a choice: skip, overwrite, or keep-both (auto-suffix the new name).
- Auto-generate a unique name (append a counter/timestamp) when a conflict is detected.
- Check for conflicts in the UI before the import call.
Example fix
// before
if target_path.exists() {
return Err(anyhow!("Backup file already exists: {file_name}"));
}
// after: auto-generate a non-conflicting name
let mut target_path = backup_dir.join(file_name);
if target_path.exists() {
let stem = source_path.file_stem().and_then(|s| s.to_str()).unwrap_or("backup");
let new_name = format!("{}-{}.zip", stem, chrono::Utc::now().timestamp());
target_path = backup_dir.join(&new_name);
} Defensive patterns
Strategy: validation
Validate before calling
fn target_unique(backup_dir: &PathBuf, file_name: &str) -> Result<PathBuf> {
let target = backup_dir.join(file_name);
if target.exists() { anyhow::bail!("Backup file already exists: {file_name}"); }
Ok(target)
} Type guard
fn target_is_free(backup_dir: &PathBuf, file_name: &str) -> bool {
!backup_dir.join(file_name).exists()
} Try / catch
if target_path.exists() {
// offer: skip / overwrite / keep-both (auto-suffix)
let new_name = format!("{}-{}.zip", stem, timestamp());
target_path = backup_dir.join(new_name);
} Prevention
- Check for name conflicts in the UI before the import call.
- Offer keep-both by auto-suffixing a timestamp/counter.
- Make overwrite an explicit user choice, never silent.
When it happens
Trigger: A backup with the same file_name is already in the local backup directory (local_backup_dir), and the source is a different path; e.g. importing 'backup-2024-01-01.zip' when one already exists locally.
Common situations: Re-importing a previously imported backup; two sources share a filename; the user exported then tries to re-import the same archive; clock-skew produced duplicate timestamped names.
Related errors
- Failed to recycle existing backup for ${path.basename(locale
- Backup file not found: {source}
- Backup path is not a file: {source}
- Failed to import backup file: {err:#?}
- Failed to copy backup file: {err:#?}
AI-assisted analysis of clash-verge-rev/clash-verge-rev@5cad0f2799 (2026-08-12).
Data as JSON: /api/errors/52adcf12b2d953d7.
Report an issue: GitHub.