NousResearch/hermes-agent · error
Hermes Desktop bridge is unavailable
Error message
Hermes Desktop bridge is unavailable
What it means
Thrown by bridge() in apps/desktop/src/lib/desktop-fs.ts:54 when `window.hermesDesktop` is undefined — the Electron preload bridge is not present. Every desktop-fs helper (read/write/rename/trash/diff) funnels through this guard, so any filesystem call made outside the desktop shell, before preload injection, or in a plain browser/jsdom context fails here first.
Source
Thrown at apps/desktop/src/lib/desktop-fs.ts:54
export function isDesktopFsRemoteMode() {
return $connection.get()?.mode === 'remote'
}
// Active profile for FS/git REST calls. Without it the Electron api bridge
// hits the primary (local) backend even when the user switched to a remote profile.
export function desktopFsProfile(): string | undefined {
return $connection.get()?.profile || undefined
}
function fsPath(endpoint: string, filePath: string) {
return `/api/fs/${endpoint}?path=${encodeURIComponent(filePath)}`
}
function bridge() {
const desktop = window.hermesDesktop
if (!desktop) {
throw new Error('Hermes Desktop bridge is unavailable')
}
return desktop
}
function remoteFsApi<T>(path: string, body?: Record<string, unknown>): Promise<T> {
return bridge().api<T>(
body ? { body, method: 'POST', path, profile: desktopFsProfile() } : { path, profile: desktopFsProfile() }
)
}
export async function readDesktopDir(path: string): Promise<HermesReadDirResult> {
if (!isDesktopFsRemoteMode()) {
return bridge().readDir(path)
}
return remoteFsApi<HermesReadDirResult>(fsPath('list', path))
}View on GitHub (pinned to c896c09c42)
Solutions
- Check for the bridge before use: `if (!window.hermesDesktop) { showUnsupported(); return }`.
- In tests, install a minimal stub: `(window as any).hermesDesktop = { api: vi.fn() }`.
- Keep desktop-fs calls inside desktop-only surfaces; for dual environments use isDesktopFsRemoteMode() and the remote REST path with the bridge check intact.
- If the bridge is unexpectedly missing inside Electron, verify the preload script is attached in the BrowserWindow webPreferences.
Example fix
// before
const entries = await readDesktopDir(path)
// after
function ensureBridge() {
if (!window.hermesDesktop) throw new Error('Desktop shell required for filesystem access')
}
ensureBridge()
const entries = await readDesktopDir(path) Defensive patterns
Strategy: type-guard
Type guard
type DesktopBridge = NonNullable<Window['hermesDesktop']>
function desktopBridgeOrThrow(): DesktopBridge {
const d = window.hermesDesktop
if (!d) throw new Error('Hermes Desktop bridge is unavailable')
return d
} Try / catch
if (!window.hermesDesktop) { renderUnavailable('File browsing requires the desktop app'); return }
try { await readDesktopDir(path) } catch (e) { if (e instanceof Error && e.message === 'Hermes Desktop bridge is unavailable') setFsUnavailable() else throw e } Prevention
- Mount desktop-fs-dependent UI only in desktop contexts
- Centralize the bridge check at feature mount (one guard per surface)
- Stub hermesDesktop in jsdom tests
- If this fires inside Electron, check preload script attachment before debugging callers
When it happens
Trigger: Calling readDesktopDir / writeDesktopFileText / any desktop-fs helper in the web dashboard or a non-Electron browser tab; invoking during early renderer startup before the preload script runs; unit tests without a hermesDesktop stub; a web preview build that imports desktop-fs.
Common situations: Shared components accidentally imported into the web build calling desktop-fs; jsdom/vitest runs; the preload bundle failing to load after an app update (disabled webSecurity flags, corrupted asar); opening the renderer URL in an external browser for debugging.
Related errors
- Hermes desktop bridge unavailable
- Hermes Desktop bridge is unavailable
- Saving is not available
- Rename is not available
- Delete is not available
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/558b6b09c63a8444.
Report an issue: GitHub.