NousResearch/hermes-agent · error · GatewayReauthRequiredError
Your remote gateway session has expired. Open Settings -> Ga
Error message
Your remote gateway session has expired. Open Settings -> Gateway and click "Sign in" again.
What it means
A GatewayReauthRequiredError thrown by resolveGatewayWsUrl when minting a fresh OAuth WebSocket ticket reports needsOauthLogin — the remote gateway session/OAuth grant has expired and no ticket can be issued until the user re-authenticates. The error message directs the user to Settings -> Gateway -> Sign in; the underlying mint failure is chained as cause.
Source
Thrown at apps/shared/src/websocket-url.ts:60
if (conn.authMode === 'oauth') {
if (!mint) {
throw new Error('This Desktop build cannot refresh OAuth WebSocket tickets. Update Hermes Desktop and try again.')
}
try {
const result = await mint(profile)
if (typeof result === 'string') {
return result
}
if (result.ok) {
return result.wsUrl
}
if (result.needsOauthLogin) {
throw new GatewayReauthRequiredError(
'Your remote gateway session has expired. Open Settings -> Gateway and click "Sign in" again.',
{ cause: new Error(result.error) }
)
}
throw new Error(result.error || 'Could not refresh the remote gateway WebSocket ticket.')
} catch (error) {
if (isGatewayReauthRequired(error)) {
throw error instanceof GatewayReauthRequiredError
? error
: new GatewayReauthRequiredError(
'Your remote gateway session has expired. Open Settings -> Gateway and click "Sign in" again.',
{ cause: error }
)
}
throw error
}View on GitHub (pinned to c896c09c42)
Solutions
- Follow the prompt: open Settings -> Gateway and click 'Sign in' to redo the OAuth flow.
- If it recurs quickly, check system clock accuracy and the gateway's session/token TTL settings.
- Handle this typed error in UI to route the user to re-auth rather than showing a generic connection failure.
Example fix
// before
catch (e) { showGenericError(e) }
// after
catch (e) {
if (isGatewayReauthRequired(e)) openGatewaySettingsForReauth()
else showGenericError(e)
} Defensive patterns
Strategy: try-catch
Type guard
function isGatewayReauthRequiredError(e: unknown): e is GatewayReauthRequiredError {
return e instanceof GatewayReauthRequiredError
|| (typeof e === 'object' && e !== null && (e as { needsOauthLogin?: unknown }).needsOauthLogin === true)
} Try / catch
try {
const url = await resolveGatewayWsUrl(deps, conn)
} catch (e) {
if (isGatewayReauthRequiredError(e)) {
routeToGatewaySignIn() // Settings -> Gateway -> Sign in
return
}
throw e
} Prevention
- Treat GatewayReauthRequiredError as a routing signal to re-auth UI, never as a generic failure.
- Refresh tickets proactively on a timer before long idle expiry windows.
- Keep system clocks synced; skew shortens effective token life.
When it happens
Trigger: Long-lived Desktop connection to a remote (or Hermes Cloud) gateway whose OAuth access/refresh token expired or was revoked; the next reconnect attempts to mint a WS ticket, the backend answers needsOauthLogin, and this typed error is raised.
Common situations: Returning to the app after days idle, refresh token revoked server-side, clock skew invalidating tokens, or gateway-side session purge.
Related errors
- Could not refresh the remote gateway WebSocket ticket.
- This Desktop build cannot refresh OAuth WebSocket tickets. U
- Gateway did not return a WS ticket.
- Reached the gateway over HTTP, but the live WebSocket (/api/
- Hermes backend for profile "${profile}" is HTTP-reachable bu
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/799f42064003a59e.
Report an issue: GitHub.