NousResearch/hermes-agent · warning · Error
Invalid delete
Error message
Invalid delete
What it means
The 'hermes:fs:trash' IPC moves a file/folder to the OS trash via shell.trashItem. Its only input validation is a non-empty trimmed target path; an empty/undefined value throws 'Invalid delete' before the shell call. Failures from trashItem itself surface as different (shell) errors.
Source
Thrown at apps/desktop/electron/main.ts:11819
const resolved = resolveRequestedPathForIpc(expandUserPath(raw), { purpose: 'Write text file' })
if (!directoryExists(path.dirname(resolved))) {
throw new Error('Parent directory does not exist')
}
await fs.promises.writeFile(resolved, text, 'utf8')
return { path: resolved }
})
// Move a file/folder to the OS trash (recoverable) — the VS Code "Delete"
// default. `shell.trashItem` routes to Finder/Explorer/Files trash per platform.
ipcMain.handle('hermes:fs:trash', async (_event, targetPath) => {
const target = String(targetPath || '').trim()
if (!target) {
throw new Error('Invalid delete')
}
await shell.trashItem(target)
return true
})
// Git-driven worktree management ("Start work" flow). Errors surface to the
// renderer as rejected promises so it can toast a friendly message.
ipcMain.handle('hermes:git:worktreeList', async (_event, repoPath) => listWorktrees(repoPath, resolveGitBinary()))
ipcMain.handle('hermes:git:worktreeAdd', async (_event, repoPath, options) =>
addWorktree(repoPath, options || {}, resolveGitBinary())
)
ipcMain.handle('hermes:git:worktreeRemove', async (_event, repoPath, worktreePath, options) =>
removeWorktree(repoPath, worktreePath, options || {}, resolveGitBinary())
)View on GitHub (pinned to c896c09c42)
Solutions
- Guard the delete action on a non-empty selected item path in the renderer
- Disable the delete affordance when no item is selected
- Distinguish this validation error from real trashItem failures (permissions, missing file) which throw different messages
Example fix
// before
onDelete={() => void ipc.invoke('hermes:fs:trash', selected?.path)}
// after
onDelete={() => { if (selected?.path) void ipc.invoke('hermes:fs:trash', selected.path) }} Defensive patterns
Strategy: validation
Validate before calling
const target = typeof targetPath === 'string' ? targetPath.trim() : ''
if (!target) { notify('Select an item to delete'); return }
await ipc.invoke('hermes:fs:trash', target) Type guard
function hasTrashTarget(v: unknown): v is string { return typeof v === 'string' && v.trim().length > 0 } Try / catch
catch (e) { if (e instanceof Error && e.message === 'Invalid delete') notify('Nothing selected to delete') else throw e } Prevention
- Disable delete actions when the selection is empty
- Resolve the focused item's path before enabling keyboard delete shortcuts
When it happens
Trigger: Renderer invokes hermes:fs:trash with '', ' ', null, or undefined — typically a delete action fired from UI state where the selected item's path is not set (nothing selected, or selection cleared by a re-render).
Common situations: Delete button enabled with an empty selection; keyboard shortcut handled before the focused-item state resolves; list virtualization returning null item for the row index.
Related errors
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/3683caabff11ba87.
Report an issue: GitHub.