{"record":{"id":"4fc39b92575cdcb3","repo":"NousResearch/hermes-agent","slug":"remote-gateway-session-token-is-required","errorCode":null,"errorMessage":"Remote gateway session token is required.","messagePattern":"Remote gateway session token is required\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/desktop/electron/main.ts","lineNumber":7014,"sourceCode":"    sshPort: (ssh || savedSsh)?.port || null,\n    sshKeyPath: (ssh || savedSsh)?.keyPath || '',\n    sshRemoteHermesPath: (ssh || savedSsh)?.remoteHermesPath || '',\n    sshRemoteProfile: (ssh || savedSsh)?.remoteProfile || '',\n    // The env override only forces the global/primary connection; a per-profile\n    // scope is never overridden by HERMES_DESKTOP_REMOTE_URL.\n    envOverride\n  }\n}\n\n// Build + validate a `{ url, authMode, token }` remote block. OAuth gateways\n// authenticate via the login-window session cookie (verified at connect time in\n// resolveRemoteBackend), so only token-auth remotes require a saved token.\n// `org` (optional) is the Hermes Cloud org slug/id the instance was discovered\n// under — persisted so Settings can reopen into the same org; omitted from the\n// block when empty so plain remote connections stay unchanged.\nfunction buildRemoteBlock(remoteUrl, authMode, token, org?: string) {\n  if (authMode !== 'oauth' && !decryptDesktopSecret(token)) {\n    throw new Error('Remote gateway session token is required.')\n  }\n\n  const block: { url: string; authMode: string; token: object; org?: string } = {\n    url: normalizeRemoteBaseUrl(remoteUrl),\n    authMode,\n    token\n  }\n\n  const orgValue = typeof org === 'string' ? org.trim() : ''\n\n  if (orgValue) {\n    block.org = orgValue\n  }\n\n  return block\n}\n\nfunction coerceDesktopConnectionConfig(input: any = {}, existing = readDesktopConnectionConfig(), options: any = {}) {","sourceCodeStart":6996,"sourceCodeEnd":7032,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/apps/desktop/electron/main.ts#L6996-L7032","documentation":"Thrown by buildRemoteBlock, the constructor for a {url, authMode, token} remote connection block. Only OAuth-auth remotes are exempt from carrying a token (they authenticate via the login-window session cookie verified at connect time in resolveRemoteBackend); for any other authMode, decryptDesktopSecret(token) must yield a value. A token that fails to decrypt — or was never saved — triggers this.","triggerScenarios":"Saving a token-mode remote connection with an empty token; a previously-saved token whose stored encoding can no longer be decrypted (keyring changed/re-encrypted); passing token as a raw string when decryptDesktopSecret expects the stored secret envelope.","commonSituations":"Settings → Gateway saved with the token field left blank while authMode is 'token'; OS keyring reset losing previously-encrypted tokens; migrating configs between machines.","solutions":["Enter and save a non-empty session token in Settings → Gateway when using token auth.","Switch the remote's authMode to 'oauth' if the gateway supports cookie-based login — then no static token is required.","If a previously saved token stopped decrypting (keyring reset), clear and re-save it."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"function hasRemoteToken(authMode, token) {\n  if (authMode === 'oauth') return true // cookie-authed at connect time\n  return Boolean(decryptDesktopSecret(token))\n}\nif (!hasRemoteToken(authMode, token)) {\n  requireTokenInput()\n}","typeGuard":"function isTokenAuthReady(authMode, token) {\n  return authMode === 'oauth' || Boolean(decryptDesktopSecret(token))\n}","tryCatchPattern":null,"preventionTips":["Block save when token mode has an empty token","Use OAuth mode where supported","Re-save tokens after a keyring reset"],"tags":["gateway","remote","auth","token","validation","desktop"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}