{"record":{"id":"0ab28626daeeac27","repo":"modelcontextprotocol/servers","slug":"destination-already-exists-destinationpath","errorCode":null,"errorMessage":"Destination already exists: ${destinationPath}","messagePattern":"Destination already exists: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/filesystem/lib.ts","lineNumber":255,"sourceCode":"}\n\n\nexport async function moveFile(sourcePath: string, destinationPath: string): Promise<void> {\n  // The move_file tool contract (and README) state the operation fails if the\n  // destination already exists. fs.rename would silently overwrite it, which is\n  // a data-loss bug, so reject up front when anything - file, directory, or\n  // symlink - occupies the target. lstat is used so an existing symlink at the\n  // destination is detected rather than followed.\n  try {\n    await fs.lstat(destinationPath);\n  } catch (error) {\n    if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n      await fs.rename(sourcePath, destinationPath);\n      return;\n    }\n    throw error;\n  }\n  throw new Error(`Destination already exists: ${destinationPath}`);\n}\n\n\n// File Editing Functions\ninterface FileEdit {\n  oldText: string;\n  newText: string;\n}\n\nexport async function applyFileEdits(\n  filePath: string,\n  edits: FileEdit[],\n  dryRun: boolean = false\n): Promise<string> {\n  // Read file content and normalize line endings\n  const content = normalizeLineEndings(await fs.readFile(filePath, 'utf-8'));\n\n  // Apply edits sequentially","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/modelcontextprotocol/servers/blob/579c3903f30044eb702a599a74b3ae77588e722e/src/filesystem/lib.ts#L237-L273","documentation":"moveFile performs a non-destructive move: it first lstat's the destination and, if anything (file, directory, or symlink) already exists there, throws instead of letting fs.rename silently overwrite it. This exists to prevent data loss, since rename(2) would otherwise replace the target atomically.","triggerScenarios":"Calling move_file(sourcePath, destinationPath) via the move_file tool where destinationPath exists on disk — including when it is only a dangling symlink (lstat detects it without following).","commonSituations":"Re-running a script that moves files without cleaning up; moving into a directory that already contains same-named files; race where another process created the destination between planning and the move.","solutions":["Delete or rename the existing destination first, then retry the move","Choose a unique destination name (e.g. append a timestamp or version suffix)","If overwrite is genuinely intended, delete the destination explicitly via an allowed tool rather than expecting move_file to clobber it"],"exampleFix":"// before\nawait move_file('/allowed/a.txt', '/allowed/b.txt'); // b.txt exists -> error\n// after\nawait move_file('/allowed/b.txt', '/allowed/b.txt.bak'); // or unlink first\nawait move_file('/allowed/a.txt', '/allowed/b.txt');","handlingStrategy":"try-catch","validationCode":"try { await fs.lstat(dest); throw new Error(`Destination exists: ${dest}`); } catch (e) { if ((e as NodeJS.ErrnoException).code !== 'ENOENT') throw e; }","typeGuard":"async function destinationIsFree(dest: string): Promise<boolean> {\n  try { await fs.lstat(dest); return false; } catch (e) { return (e as NodeJS.ErrnoException).code === 'ENOENT'; }\n}","tryCatchPattern":"try {\n  await move_file(src, dest);\n} catch (err) {\n  if (err.message.startsWith('Destination already exists')) {\n    // pick a unique name or archive the existing destination, then retry\n  } else throw err;\n}","preventionTips":["Check destination availability with lstat before issuing the move","Generate unique destination names (timestamps, counters) in scripts","Make move scripts idempotent: skip or archive when destination exists","Clean up partial-run artifacts that occupy destination names"],"tags":["filesystem","move","file-exists","conflict"],"backgroundTag":"destination-already-exists","analyzedSha":"579c3903f30044eb702a599a74b3ae77588e722e","analyzedAt":"2026-09-01T06:06:22.520Z","contentChangedAt":"2026-09-01T06:06:22.520Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}