{"record":{"id":"dee094c458e7e897","repo":"laurent22/joplin","slug":"error-destination-already-exists","errorCode":null,"errorMessage":"Error! Destination already exists","messagePattern":"Error! Destination already exists","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/app-mobile/utils/fs-driver/tarCreate.ts","lineNumber":26,"sourceCode":"\nconst logger = Logger.create('fs-driver-rn');\n\nexport interface TarCreateOptions {\n\tcwd: string;\n\tfile: string;\n}\n\n// TODO: Support glob patterns, which are currently supported by the\n//       node fsDriver.\n\nconst tarCreate = async (options: TarCreateOptions, filePaths: string[]) => {\n\t// Choose a default cwd if not given\n\tconst cwd = options.cwd ?? shim.fsDriver().getAppDirectoryPath();\n\tconst file = resolve(cwd, options.file);\n\n\tconst fsDriver = shim.fsDriver();\n\tif (await fsDriver.exists(file)) {\n\t\tthrow new Error('Error! Destination already exists');\n\t}\n\n\tconst pack = tarStreamPack();\n\n\tconst errors: Error[] = [];\n\tpack.addListener('error', error => {\n\t\tlogger.error(`Tar error: ${error}`);\n\t\terrors.push(error);\n\t});\n\n\tfor (const path of filePaths) {\n\t\tconst absPath = resolve(cwd, path);\n\t\tconst stat = await fsDriver.stat(absPath);\n\t\tconst sizeBytes: number = stat.size;\n\n\t\tconst entry = pack.entry({ name: path, size: sizeBytes }, (error) => {\n\t\t\tif (error) {\n\t\t\t\tlogger.error(`Tar error: ${error}`);","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/laurent22/joplin/blob/2654b33620775080d1d59c552259d41e33dad3d2/packages/app-mobile/utils/fs-driver/tarCreate.ts#L8-L44","documentation":"Thrown by `tarCreate` when the destination tar file (resolved from `options.cwd` + `options.file`) already exists, before packing begins. This prevents silently overwriting a previous backup. It is a pure precondition check on the resolved output path.","triggerScenarios":"Calling `tarCreate(options, filePaths)` where `resolve(cwd, options.file)` resolves to an existing file. Typically when creating a backup with a fixed filename that already exists from a prior run.","commonSituations":"Repeated backup runs that reuse the same filename; manual copies left in the output directory; a previous run succeeded and the caller forgot to delete the old archive.","solutions":["Delete or rename the existing destination before calling `tarCreate`.","Use a timestamped filename so each run produces a unique archive.","Pre-check: `if (await fsDriver.exists(file)) await fsDriver.remove(file);`."],"exampleFix":"// before\nawait tarCreate({ cwd, file: 'backup.tar' }, filePaths);\n\n// after\nconst file = resolve(cwd, 'backup.tar');\nif (await shim.fsDriver().exists(file)) {\n  await shim.fsDriver().remove(file);\n}\nawait tarCreate({ cwd, file: 'backup.tar' }, filePaths);","handlingStrategy":"validation","validationCode":"const dest = resolve(options.cwd ?? shim.fsDriver().getAppDirectoryPath(), options.file);\nif (await shim.fsDriver().exists(dest)) {\n  await shim.fsDriver().remove(dest);\n}\nawait tarCreate(options, filePaths);","typeGuard":"null","tryCatchPattern":"try {\n  await tarCreate(options, filePaths);\n} catch (error) {\n  if (/Destination already exists/i.test(error.message)) {\n    await shim.fsDriver().remove(resolve(options.cwd ?? shim.fsDriver().getAppDirectoryPath(), options.file));\n    return tarCreate(options, filePaths);\n  }\n  throw error;\n}","preventionTips":["Use timestamped output filenames to avoid collisions.","Delete the prior archive before re-running a backup.","Pre-check existence at the resolved path, not the relative one."],"tags":["filesystem","tar","backup","precondition","mobile"],"backgroundTag":null,"analyzedSha":"2654b33620775080d1d59c552259d41e33dad3d2","analyzedAt":"2026-08-12T14:26:46.263Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}