NousResearch/hermes-agent · error
Hermes Desktop bridge is unavailable
Error message
Hermes Desktop bridge is unavailable
What it means
Thrown by desktopApi() in apps/desktop/src/lib/desktop-git.ts:25 when `window.hermesDesktop` is absent. desktop-git routes git operations through the Electron bridge (`desktop.api`) — locally via window.hermesDesktop.git, remotely via the dashboard REST /api/git/* mirror — but both shapes still need the base desktop bridge to make the api call. Outside the desktop shell there is no transport at all.
Source
Thrown at apps/desktop/src/lib/desktop-git.ts:25
HermesReviewList,
HermesReviewShipInfo
} from '@/global'
import { desktopFsProfile, isDesktopFsRemoteMode } from './desktop-fs'
// Remote-aware git facade. Locally the desktop runs git through Electron
// (window.hermesDesktop.git); on a remote gateway that's the wrong filesystem,
// so we mirror the same surface over the dashboard REST API (/api/git/*) — the
// coding rail, worktree lanes, review pane, and branch ops then act on the
// BACKEND repo where sessions actually run. Mirrors desktop-fs.ts.
type GitBridge = NonNullable<NonNullable<Window['hermesDesktop']>['git']>
function desktopApi<T>(path: string, body?: Record<string, unknown>): Promise<T> {
const desktop = window.hermesDesktop
if (!desktop) {
throw new Error('Hermes Desktop bridge is unavailable')
}
return desktop.api<T>(
body ? { body, method: 'POST', path, profile: desktopFsProfile() } : { path, profile: desktopFsProfile() }
)
}
function gitGet<T>(route: string, params: Record<string, boolean | null | string | undefined>): Promise<T> {
const query = new URLSearchParams()
for (const [key, value] of Object.entries(params)) {
if (value !== null && value !== undefined) {
query.set(key, String(value))
}
}
return desktopApi<T>(`/api/git/${route}?${query.toString()}`)
}View on GitHub (pinned to c896c09c42)
Solutions
- Feature-gate git surfaces on the bridge: `if (!window.hermesDesktop) return disabledState`.
- Stub window.hermesDesktop = { api: vi.fn() } in unit tests of git-dependent components.
- Ensure git components are only mounted in desktop-only routes.
- Verify preload attachment if this fires inside Electron proper.
Example fix
// before
const status = await gitStatus(repoRoot)
// after
if (!window.hermesDesktop) {
setGitUnavailable('Git tooling is available only in the Hermes desktop app')
return
}
const status = await gitStatus(repoRoot) Defensive patterns
Strategy: type-guard
Type guard
function hasDesktopBridge(w: Window): w is Window & { hermesDesktop: NonNullable<Window['hermesDesktop']> } {
return Boolean((w as any).hermesDesktop)
} Try / catch
if (!hasDesktopBridge(window)) { setGitUnavailable('Git tooling is desktop-only'); return }
try { const status = await gitStatus(repoRoot) } catch (e) { if (e instanceof Error && e.message === 'Hermes Desktop bridge is unavailable') setGitUnavailable() else throw e } Prevention
- Mount git surfaces (coding rail, review pane, worktree lanes) only in desktop routes
- One shared capability check per surface, not per operation
- Mock window.hermesDesktop.api for git facade tests
- Remote git goes through /api/git/* but still requires the base bridge — never assume browser fetch works here
When it happens
Trigger: Any desktop-git helper call (status, file-diff, branch ops, worktree lanes, review pane) executed in a browser/web build or jsdom test without a hermesDesktop stub; calling before preload injection completes.
Common situations: Git-dependent UI (coding rail, review pane) rendered in the web dashboard; tests for git facades without bridge mocks; debugging the renderer in an external browser.
Related errors
- Hermes desktop bridge unavailable
- Hermes Desktop bridge is unavailable
- Desktop preview browser bridge is unavailable
- gh pr create failed (is gh installed and authenticated?)
- Branch name is required.
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/7e78086dd5cce684.
Report an issue: GitHub.