{"record":{"id":"8147d7ecdab45fff","repo":"can1357/oh-my-pi","slug":"rename-target-already-exists-formatpathrelative","errorCode":null,"errorMessage":"rename target already exists: ${formatPathRelativeToCwd(newPath, cwd)}","messagePattern":"rename target already exists: (.+?)","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/lsp/edits.ts","lineNumber":371,"sourceCode":"\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tapplied.push(`Created ${formatPathRelativeToCwd(filePath, cwd)}`);\n\t\t\t\trecord({ kind: \"create\", uri: op.uri });\n\t\t\t} else if (op.kind === \"rename\") {\n\t\t\t\tconst oldPath = uriToFile(op.oldUri);\n\t\t\t\tconst newPath = uriToFile(op.newUri);\n\t\t\t\tawait fs.mkdir(path.dirname(newPath), { recursive: true });\n\t\t\t\tif (oldPath !== newPath) {\n\t\t\t\t\t// Displace an overwritten destination into a kernel-reserved sibling\n\t\t\t\t\t// temp dir (same filesystem, so the moves stay atomic) instead of\n\t\t\t\t\t// deleting it, so a failed rename (EXDEV, permissions) can restore\n\t\t\t\t\t// it and leave the workspace exactly as it was.\n\t\t\t\t\tlet displaced: { dir: string; file: string } | undefined;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst targetStat = await fs.lstat(newPath);\n\t\t\t\t\t\tif (!op.options?.overwrite) {\n\t\t\t\t\t\t\tif (op.options?.ignoreIfExists) continue;\n\t\t\t\t\t\t\tthrow new ToolError(`rename target already exists: ${formatPathRelativeToCwd(newPath, cwd)}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Only displace the destination when it is a distinct file. On a\n\t\t\t\t\t\t// case-insensitive filesystem a case-only rename resolves both\n\t\t\t\t\t\t// paths to the same inode; moving newPath aside would move the\n\t\t\t\t\t\t// source, so let fs.rename change the case in place instead.\n\t\t\t\t\t\tconst sourceStat = await fs.lstat(oldPath);\n\t\t\t\t\t\tif (sourceStat.dev !== targetStat.dev || sourceStat.ino !== targetStat.ino) {\n\t\t\t\t\t\t\tconst holdDir = await fs.mkdtemp(path.join(path.dirname(newPath), \".omp-displaced-\"));\n\t\t\t\t\t\t\tconst holdFile = path.join(holdDir, path.basename(newPath));\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tawait fs.rename(newPath, holdFile);\n\t\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\t\tawait fs.rm(holdDir, { recursive: true, force: true }).catch(() => {});\n\t\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tdisplaced = { dir: holdDir, file: holdFile };\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (error) {","sourceCodeStart":353,"sourceCodeEnd":389,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/lsp/edits.ts#L353-L389","documentation":"When applying a WorkspaceEdit containing a RenameFile operation, the destination already exists on disk. Without options.overwrite the library refuses to silently destroy the existing file; without ignoreIfExists it also won't skip, so it throws to keep the workspace consistent (the surrounding code restores any displaced files on failure).","triggerScenarios":"A server-issued rename (e.g. file rename refactor) targets a path that already exists and the RenameFile options carry neither overwrite:true nor ignoreIfExists:true.","commonSituations":"Renaming a file to a name that already exists in the same directory; case-insensitive filesystems where target differs only in case; re-running an edit after a partial application.","solutions":["Check whether the target path should exist; delete or move it if the rename is intended to replace it","If replacement is intended, ensure the server sets overwrite:true in the RenameFile options","If skipping is intended, ensure the server sets ignoreIfExists:true"],"exampleFix":"// before\n{ kind: \"rename\", oldUri, newUri }\n// after (intentional replace)\n{ kind: \"rename\", oldUri, newUri, options: { overwrite: true } }","handlingStrategy":"validation","validationCode":"import * as fs from 'node:fs/promises';\nlet exists = false;\ntry { await fs.lstat(newPath); exists = true; } catch {}\nif (exists && !op.options?.overwrite && !op.options?.ignoreIfExists) {\n  throw new Error(`target exists: ${newPath}`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await applyWorkspaceEdit(edit, cwd);\n} catch (err) {\n  if (err.message.startsWith('rename target already exists:')) {\n    // decide: prompt user, or re-issue edit with options: { overwrite: true }\n  }\n  throw err;\n}","preventionTips":["Check the destination path before issuing renames to existing files","Ensure servers set overwrite or ignoreIfExists on RenameFile operations when appropriate","Be careful with case-only renames on case-insensitive filesystems"],"tags":["lsp","filesystem","rename","workspace-edit"],"backgroundTag":"rename-target-already-exists","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}