NousResearch/hermes-agent · warning · Error
"${name}" already exists
Error message
"${name}" already exists What it means
The rename IPC computes the destination as path.join(dirname(src), name) and refuses to overwrite: if fs.existsSync(dst) is true (and dst !== src), it throws '"<name>" already exists'. This is a collision guard so an in-place rename never clobbers an existing file or folder.
Source
Thrown at apps/desktop/electron/main.ts:11777
// Rename a file/folder in place. The renderer passes the existing path + a new
// base name; the destination is resolved in the SAME parent dir so a rename can
// never move the item elsewhere or traverse out. Rejects on a name collision.
ipcMain.handle('hermes:fs:rename', async (_event, targetPath, newName) => {
const src = String(targetPath || '').trim()
const name = String(newName || '').trim()
if (!src || !name || name === '.' || name === '..' || name.includes('/') || name.includes('\\')) {
throw new Error('Invalid rename')
}
const dst = path.join(path.dirname(src), name)
if (dst === src) {
return { path: dst }
}
if (fs.existsSync(dst)) {
throw new Error(`"${name}" already exists`)
}
await fs.promises.rename(src, dst)
return { path: dst }
})
// Write a small UTF-8 text file (e.g. a project's IDEA.md at creation). The path
// is hardened (resolveRequestedPathForIpc) and the parent must already exist —
// this never creates directory trees or escapes the allowed roots, and content
// is size-capped so it can't be abused as a bulk-write primitive.
ipcMain.handle('hermes:fs:writeText', async (_event, filePath, content) => {
const raw = String(filePath || '').trim()
if (!raw) {
throw new Error('Invalid path')
}
View on GitHub (pinned to c896c09c42)
Solutions
- Choose a different name, or delete/trash the existing item first (hermes:fs:trash) if it is truly disposable
- Pre-check in the UI: existsSync-style duplicate detection or a directory listing before submitting the rename
- On macOS/Windows remember name comparison is case-insensitive at the FS level even though the guard compares strings
Example fix
// before
await ipc.invoke('hermes:fs:rename', path, name)
// after
const siblings = await ipc.invoke('hermes:fs:list', dirname(path))
if (siblings.some(s => s.name === name)) return setError(`"${name}" already exists`)
await ipc.invoke('hermes:fs:rename', path, name) Defensive patterns
Strategy: validation
Validate before calling
const siblings: { name: string }[] = await listDir(dirname(src))
if (siblings.some(s => s.name === name)) { setRenameError(`"${name}" already exists`); return }
await ipc.invoke('hermes:fs:rename', src, name) Try / catch
catch (e) { if (e instanceof Error && e.message.endsWith('already exists')) setRenameError(e.message) else throw e } Prevention
- Check the target directory listing for the new name before submitting
- On case-insensitive filesystems compare names case-insensitively
- Offer an auto-suffix ('name (2)') when a collision is detected
When it happens
Trigger: Renaming to a name that already exists in the same directory — including case-only collisions on case-insensitive filesystems (macOS/Windows: 'readme.md' vs 'README.md' when dst !== src does not hold, so case changes pass, but sibling files differing only in extension case can collide), or renaming to the current name of another item.
Common situations: Renaming a file to 'untitled' when 'untitled' already exists; merge conflicts leaving duplicate-named files; batch UIs auto-generating names that clash.
Related errors
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/c86146ffaa10f0b2.
Report an issue: GitHub.