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

  1. Gate the delete/trash UI on the capability: `if (!window.hermesDesktop?.trashPath) disableDelete()`.
  2. Update the desktop shell and restart so trashPath is exposed.
  3. On remote sessions, delete through the backend FS API instead of the local trash.
  4. 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

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


AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14). Data as JSON: /api/errors/92c4ce88b04ec4ab. Report an issue: GitHub.