{"record":{"id":"52adcf12b2d953d7","repo":"clash-verge-rev/clash-verge-rev","slug":"backup-file-already-exists-file-name","errorCode":null,"errorMessage":"Backup file already exists: {file_name}","messagePattern":"Backup file already exists: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/src/feat/backup.rs","lineNumber":214,"sourceCode":"    let file_name = source_path\n        .file_name()\n        .and_then(|name| name.to_str())\n        .ok_or_else(|| anyhow!(\"Invalid backup file name\"))?;\n\n    let backup_dir = local_backup_dir()?;\n    let target_path = backup_dir.join(file_name);\n\n    if target_path == source_path {\n        // Already located in the backup directory\n        return Ok(file_name.to_string().into());\n    }\n\n    if let Some(parent) = target_path.parent() {\n        fs::create_dir_all(parent).await?;\n    }\n\n    if target_path.exists() {\n        return Err(anyhow!(\"Backup file already exists: {file_name}\"));\n    }\n\n    fs::copy(&source_path, &target_path)\n        .await\n        .map_err(|err| anyhow!(\"Failed to import backup file: {err:#?}\"))?;\n\n    Ok(file_name.to_string().into())\n}\n\nasync fn move_file(from: PathBuf, to: PathBuf) -> Result<()> {\n    if let Some(parent) = to.parent() {\n        fs::create_dir_all(parent).await?;\n    }\n\n    match fs::rename(&from, &to).await {\n        Ok(_) => Ok(()),\n        Err(rename_err) => {\n            // Attempt copy + remove as fallback, covering cross-device moves","sourceCodeStart":196,"sourceCodeEnd":232,"githubUrl":"https://github.com/clash-verge-rev/clash-verge-rev/blob/5cad0f2799e74b1105e133bcfc2a45f5c1370ef1/src-tauri/src/feat/backup.rs#L196-L232","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nif target_path.exists() {\n    return Err(anyhow!(\"Backup file already exists: {file_name}\"));\n}\n\n// after: auto-generate a non-conflicting name\nlet mut target_path = backup_dir.join(file_name);\nif target_path.exists() {\n    let stem = source_path.file_stem().and_then(|s| s.to_str()).unwrap_or(\"backup\");\n    let new_name = format!(\"{}-{}.zip\", stem, chrono::Utc::now().timestamp());\n    target_path = backup_dir.join(&new_name);\n}","handlingStrategy":"validation","validationCode":"fn target_unique(backup_dir: &PathBuf, file_name: &str) -> Result<PathBuf> {\n    let target = backup_dir.join(file_name);\n    if target.exists() { anyhow::bail!(\"Backup file already exists: {file_name}\"); }\n    Ok(target)\n}","typeGuard":"fn target_is_free(backup_dir: &PathBuf, file_name: &str) -> bool {\n    !backup_dir.join(file_name).exists()\n}","tryCatchPattern":"if target_path.exists() {\n    // offer: skip / overwrite / keep-both (auto-suffix)\n    let new_name = format!(\"{}-{}.zip\", stem, timestamp());\n    target_path = backup_dir.join(new_name);\n}","preventionTips":["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."],"tags":["backup","conflict","filesystem","duplicate","import"],"analyzedSha":"5cad0f2799e74b1105e133bcfc2a45f5c1370ef1","analyzedAt":"2026-08-12T03:25:57.699Z","schemaVersion":2},"datasetVersion":"2026-08-12T08:17:17.861Z"}