{"record":{"id":"ae302525eff3f346","repo":"NousResearch/hermes-agent","slug":"hermes-desktop-remote-url-is-set-but-hermes-deskto","errorCode":null,"errorMessage":"HERMES_DESKTOP_REMOTE_URL is set but HERMES_DESKTOP_REMOTE_TOKEN is not. Both must be provided to connect to a remote Hermes backend.","messagePattern":"HERMES_DESKTOP_REMOTE_URL is set but HERMES_DESKTOP_REMOTE_TOKEN is not\\. Both must be provided to connect to a remote Hermes backend\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/desktop/electron/main.ts","lineNumber":7567,"sourceCode":"    const token = override.authMode === 'oauth' ? null : decryptDesktopSecret(override.token)\n\n    return buildRemoteConnection(\n      override.url,\n      override.authMode,\n      token,\n      'profile',\n      undefined,\n      config.profiles?.[connectionScopeKey(profile)]?.mode === 'cloud' ? 'cloud' : 'url'\n    )\n  }\n\n  // 2. Env override (global, token-auth only).\n  const rawEnvUrl = process.env.HERMES_DESKTOP_REMOTE_URL\n  const rawEnvToken = process.env.HERMES_DESKTOP_REMOTE_TOKEN\n\n  if (rawEnvUrl) {\n    if (!rawEnvToken) {\n      throw new Error(\n        'HERMES_DESKTOP_REMOTE_URL is set but HERMES_DESKTOP_REMOTE_TOKEN is not. ' +\n          'Both must be provided to connect to a remote Hermes backend.'\n      )\n    }\n\n    return buildRemoteConnection(rawEnvUrl, 'token', rawEnvToken, 'env')\n  }\n\n  // 3. Global remote.\n  if (config.mode === 'ssh') {\n    const ssh = normalizeSshConfig({ mode: 'ssh', ...(config.remote || {}) })\n\n    if (!ssh) {\n      throw new Error('SSH remote mode is selected but no host is configured.')\n    }\n\n    const reuseToken = decryptDesktopSecret(config.remote?.token)\n","sourceCodeStart":7549,"sourceCodeEnd":7585,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/apps/desktop/electron/main.ts#L7549-L7585","documentation":"Env-override validation during remote-connection resolution: HERMES_DESKTOP_REMOTE_URL is set but HERMES_DESKTOP_REMOTE_TOKEN is not. The env override is global and token-auth only — the two variables form one credential pair, and a URL without a token is treated as a misconfiguration rather than silently falling through to the next resolution step (global remote config).","triggerScenarios":"Exporting only HERMES_DESKTOP_REMOTE_URL (e.g. copying half a documented snippet); a shell profile that sets the URL unconditionally but the token from another file that failed to source; typos in the token variable name.","commonSituations":".bashrc/.zshrc set up piecemeal; CI/launchd environments where only one var was injected; the token containing trailing whitespace/newline so shells drop it.","solutions":["Set both variables together: export HERMES_DESKTOP_REMOTE_URL=... and export HERMES_DESKTOP_REMOTE_TOKEN=...","Unset HERMES_DESKTOP_REMOTE_URL if you intend to use the in-app Settings → Gateway configuration instead.","Check for typos/whitespace in the token variable name and value; quote values containing special characters."],"exampleFix":"# before\nexport HERMES_DESKTOP_REMOTE_URL=https://hermes.example.com\n\n# after\nexport HERMES_DESKTOP_REMOTE_URL=https://hermes.example.com\nexport HERMES_DESKTOP_REMOTE_TOKEN='your-session-token'","handlingStrategy":"validation","validationCode":"function envRemotePairComplete() {\n  const url = process.env.HERMES_DESKTOP_REMOTE_URL\n  const token = process.env.HERMES_DESKTOP_REMOTE_TOKEN\n  return !url || Boolean(url && token)\n}","typeGuard":null,"tryCatchPattern":"try {\n  await resolveConnection()\n} catch (e) {\n  if (/HERMES_DESKTOP_REMOTE_URL is set but/.test(e.message)) {\n    fixEnvironmentPair() // set the token or unset the URL\n  } else throw e\n}","preventionTips":["Always export the URL and token variables together","Quote token values in shell profiles","Unset the URL variable when you'd rather configure via Settings"],"tags":["environment","remote","gateway","token","config","desktop"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}