{"record":{"id":"b66c9547738db652","repo":"NousResearch/hermes-agent","slug":"failed-to-encrypt-the-remote-gateway-token-for-sec","errorCode":null,"errorMessage":"Failed to encrypt the remote gateway token for secure storage${detail}. Set HERMES_DESKTOP_REMOTE_URL and HERMES_DESKTOP_REMOTE_TOKEN in your environment as a fallback.","messagePattern":"Failed to encrypt the remote gateway token for secure storage(.+?)\\. Set HERMES_DESKTOP_REMOTE_URL and HERMES_DESKTOP_REMOTE_TOKEN in your environment as a fallback\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/desktop/electron/hardening.ts","lineNumber":207,"sourceCode":"      return { encoding: 'plain', value: raw }\n    }\n\n    throw new Error(\n      'Secure token storage is unavailable (no OS keyring service was found), so Hermes Desktop cannot save remote gateway tokens. ' +\n        'Either enable an OS keyring (e.g. GNOME Keyring or KWallet providing org.freedesktop.secrets) and try again, ' +\n        'confirm the plain-text storage option when prompted in Settings → Gateway, ' +\n        'or set HERMES_DESKTOP_REMOTE_URL and HERMES_DESKTOP_REMOTE_TOKEN in your environment.'\n    )\n  }\n\n  try {\n    return {\n      encoding: SAFE_STORAGE_ENCODING,\n      value: safeStorageApi.encryptString(raw).toString('base64')\n    }\n  } catch (error) {\n    const detail = error instanceof Error && error.message ? ` (${error.message})` : ''\n    throw new Error(\n      `Failed to encrypt the remote gateway token for secure storage${detail}. ` +\n        'Set HERMES_DESKTOP_REMOTE_URL and HERMES_DESKTOP_REMOTE_TOKEN in your environment as a fallback.'\n    )\n  }\n}\n\n// Keyring-less Linux (e.g. Hyprland/Sway with no GNOME Keyring or KWallet):\n// `--password-store=basic` selects Electron's built-in \"basic\" backend, but\n// Electron only counts it as available once setUsePlainTextEncryption(true) is\n// called. The caller runs this on whenReady, before createWindow() and anything\n// that could touch safeStorage, so the switch takes effect for the whole run.\n//\n// Semantics are deliberately narrow: only linux, only the exact 'basic' switch\n// value (never 'gnome-libsecret', 'kwallet', '', etc.), and only when the\n// method exists (older/mocked safeStorage may lack it) and does not throw.\n// Anything else is a no-op. Returns true only when it actually flipped the flag,\n// so the caller (and tests) can distinguish \"enabled\" from \"left untouched\".\n// Never throws: a failure here is non-fatal — encryption simply stays","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/apps/desktop/electron/hardening.ts#L189-L225","documentation":"Thrown when safeStorage IS available (the availability check passed) but the actual encryptString(raw) call throws. This distinguishes it from the 'no keyring' error: here the OS keyring exists, yet the encryption operation itself failed — often a locked keyring, a D-Bus hiccup, or a backend quirk. The original error message is appended as detail.","triggerScenarios":"Keyring service present but locked at the moment of the call; keyring daemon crashed mid-call; KWallet timing out; any exception from safeStorageApi.encryptString(raw).","commonSituations":"Saving a gateway token right after login before the keyring unlocks; flaky D-Bus sessions; unusual keyring backends (keepassxc proxy) that partially implement the API.","solutions":["Unlock the keyring (open the keyring prompt / `gnome-keyring-daemon --unlock`) and retry the save.","Restart the keyring service or the D-Bus session if it crashed.","As a workaround set HERMES_DESKTOP_REMOTE_URL and HERMES_DESKTOP_REMOTE_TOKEN in the environment, as the message suggests.","Read the appended detail in parentheses — it carries the underlying error text for diagnosis."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await saveRemoteToken(token)\n} catch (e) {\n  if (/Failed to encrypt/.test(e.message)) {\n    await notifyUser('Unlock your OS keyring and retry, or use env-var credentials.')\n  } else throw e\n}","preventionTips":["Unlock the keyring before saving secrets","Read the appended detail to identify the underlying keyring error","Prefer env-var credentials on flaky keyring setups"],"tags":["desktop","keyring","safe-storage","encryption","electron","secrets"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}