{"record":{"id":"799f42064003a59e","repo":"NousResearch/hermes-agent","slug":"your-remote-gateway-session-has-expired-open-sett","errorCode":null,"errorMessage":"Your remote gateway session has expired. Open Settings -> Gateway and click \"Sign in\" again.","messagePattern":"Your remote gateway session has expired\\. Open Settings -> Gateway and click \"Sign in\" again\\.","errorType":"exception","errorClass":"GatewayReauthRequiredError","httpStatus":null,"severity":"error","filePath":"apps/shared/src/websocket-url.ts","lineNumber":60,"sourceCode":"\n  if (conn.authMode === 'oauth') {\n    if (!mint) {\n      throw new Error('This Desktop build cannot refresh OAuth WebSocket tickets. Update Hermes Desktop and try again.')\n    }\n\n    try {\n      const result = await mint(profile)\n\n      if (typeof result === 'string') {\n        return result\n      }\n\n      if (result.ok) {\n        return result.wsUrl\n      }\n\n      if (result.needsOauthLogin) {\n        throw new GatewayReauthRequiredError(\n          'Your remote gateway session has expired. Open Settings -> Gateway and click \"Sign in\" again.',\n          { cause: new Error(result.error) }\n        )\n      }\n\n      throw new Error(result.error || 'Could not refresh the remote gateway WebSocket ticket.')\n    } catch (error) {\n      if (isGatewayReauthRequired(error)) {\n        throw error instanceof GatewayReauthRequiredError\n          ? error\n          : new GatewayReauthRequiredError(\n              'Your remote gateway session has expired. Open Settings -> Gateway and click \"Sign in\" again.',\n              { cause: error }\n            )\n      }\n\n      throw error\n    }","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/apps/shared/src/websocket-url.ts#L42-L78","documentation":"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.","triggerScenarios":"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.","commonSituations":"Returning to the app after days idle, refresh token revoked server-side, clock skew invalidating tokens, or gateway-side session purge.","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."],"exampleFix":"// before\ncatch (e) { showGenericError(e) }\n\n// after\ncatch (e) {\n  if (isGatewayReauthRequired(e)) openGatewaySettingsForReauth()\n  else showGenericError(e)\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isGatewayReauthRequiredError(e: unknown): e is GatewayReauthRequiredError {\n  return e instanceof GatewayReauthRequiredError\n    || (typeof e === 'object' && e !== null && (e as { needsOauthLogin?: unknown }).needsOauthLogin === true)\n}","tryCatchPattern":"try {\n  const url = await resolveGatewayWsUrl(deps, conn)\n} catch (e) {\n  if (isGatewayReauthRequiredError(e)) {\n    routeToGatewaySignIn() // Settings -> Gateway -> Sign in\n    return\n  }\n  throw e\n}","preventionTips":["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."],"tags":["oauth","websocket","auth-expiry","gateway","shared"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}