NousResearch/hermes-agent · error
Delete is not available
Error message
Delete is not available
What it means
Thrown by trashDesktopPath() in apps/desktop/src/lib/desktop-fs.ts:153 when the bridge lacks a `trashPath` method. Moving a file to the OS trash (recoverable delete) is a local-only Electron IPC capability; without it the function refuses, which is the safe behavior — a fallback that permanently deleted would be worse than the error.
Source
Thrown at apps/desktop/src/lib/desktop-fs.ts:153
// Rename a file/folder in place; returns the new absolute path. Local only.
export async function renameDesktopPath(path: string, newName: string): Promise<string> {
const desktop = bridge()
if (!desktop.renamePath) {
throw new Error('Rename is not available')
}
const result = await desktop.renamePath(path, newName)
return result.path
}
// Move a file/folder to the OS trash (recoverable). Local only.
export async function trashDesktopPath(path: string): Promise<void> {
const desktop = bridge()
if (!desktop.trashPath) {
throw new Error('Delete is not available')
}
await desktop.trashPath(path)
}
export async function copyTextToClipboard(text: string): Promise<void> {
await bridge().writeClipboard(text)
}
// Working-tree-vs-HEAD diff for one file. Empty when unchanged / not a repo.
// Remote gateway → backend git (/api/git/file-diff); local → Electron git.
export async function desktopFileDiff(repoRoot: string, filePath: string): Promise<string> {
if (isDesktopFsRemoteMode()) {
const result = await remoteFsApi<{ diff: string }>(
`/api/git/file-diff?path=${encodeURIComponent(repoRoot)}&file=${encodeURIComponent(filePath)}`
)
return result.diff || ''View on GitHub (pinned to c896c09c42)
Solutions
- Gate the delete/trash UI on the capability: `if (!window.hermesDesktop?.trashPath) disableDelete()`.
- Update the desktop shell and restart so trashPath is exposed.
- On remote sessions, delete through the backend FS API instead of the local trash.
- Stub trashPath in bridge mocks for tests.
Example fix
// before
await trashDesktopPath(path)
// after
if (!window.hermesDesktop?.trashPath) {
notify({ kind: 'error', title: 'Delete requires an updated desktop app' })
return
}
await trashDesktopPath(path) Defensive patterns
Strategy: type-guard
Validate before calling
function canTrash(): boolean {
return typeof window.hermesDesktop?.trashPath === 'function'
} Type guard
function hasTrash(w: Window): w is Window & { hermesDesktop: { trashPath: (p: string) => Promise<void> } } {
return typeof (w as any).hermesDesktop?.trashPath === 'function'
} Try / catch
if (!canTrash()) { disableDeleteAction(); return }
try { await trashDesktopPath(path) } catch (e) { notifyError(e, 'Delete failed') } Prevention
- Never substitute an unconditional delete when trashPath is missing — the error is the safe outcome
- Gate destructive UI on capability presence
- Keep local-only capabilities hidden in remote mode
- Stub trashPath in tests
When it happens
Trigger: Calling trashDesktopPath on an older shell without the trashPath IPC; a remote-mode session where local-only capabilities are not offered; a bridge stub in tests missing trashPath.
Common situations: Version skew between renderer and Electron shell; delete button shown in a context where the capability genuinely doesn't exist; web preview importing the file explorer UI.
Related errors
- Rename is not available
- Hermes Desktop bridge is unavailable
- Saving is not available
- Desktop preview browser bridge is unavailable
- Could not write artifact file
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/92c4ce88b04ec4ab.
Report an issue: GitHub.