NousResearch/hermes-agent · error · Error
HERMES_DESKTOP_REMOTE_URL is set but HERMES_DESKTOP_REMOTE_T
Error message
HERMES_DESKTOP_REMOTE_URL is set but HERMES_DESKTOP_REMOTE_TOKEN is not. Both must be provided to connect to a remote Hermes backend.
What it means
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).
Source
Thrown at apps/desktop/electron/main.ts:7567
const token = override.authMode === 'oauth' ? null : decryptDesktopSecret(override.token)
return buildRemoteConnection(
override.url,
override.authMode,
token,
'profile',
undefined,
config.profiles?.[connectionScopeKey(profile)]?.mode === 'cloud' ? 'cloud' : 'url'
)
}
// 2. Env override (global, token-auth only).
const rawEnvUrl = process.env.HERMES_DESKTOP_REMOTE_URL
const rawEnvToken = process.env.HERMES_DESKTOP_REMOTE_TOKEN
if (rawEnvUrl) {
if (!rawEnvToken) {
throw new Error(
'HERMES_DESKTOP_REMOTE_URL is set but HERMES_DESKTOP_REMOTE_TOKEN is not. ' +
'Both must be provided to connect to a remote Hermes backend.'
)
}
return buildRemoteConnection(rawEnvUrl, 'token', rawEnvToken, 'env')
}
// 3. Global remote.
if (config.mode === 'ssh') {
const ssh = normalizeSshConfig({ mode: 'ssh', ...(config.remote || {}) })
if (!ssh) {
throw new Error('SSH remote mode is selected but no host is configured.')
}
const reuseToken = decryptDesktopSecret(config.remote?.token)
View on GitHub (pinned to c896c09c42)
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.
Example fix
# before export HERMES_DESKTOP_REMOTE_URL=https://hermes.example.com # after export HERMES_DESKTOP_REMOTE_URL=https://hermes.example.com export HERMES_DESKTOP_REMOTE_TOKEN='your-session-token'
Defensive patterns
Strategy: validation
Validate before calling
function envRemotePairComplete() {
const url = process.env.HERMES_DESKTOP_REMOTE_URL
const token = process.env.HERMES_DESKTOP_REMOTE_TOKEN
return !url || Boolean(url && token)
} Try / catch
try {
await resolveConnection()
} catch (e) {
if (/HERMES_DESKTOP_REMOTE_URL is set but/.test(e.message)) {
fixEnvironmentPair() // set the token or unset the URL
} else throw e
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: .bashrc/.zshrc set up piecemeal; CI/launchd environments where only one var was injected; the token containing trailing whitespace/newline so shells drop it.
Related errors
- Remote gateway session token is required.
- Remote Hermes gateway is selected, but no session token is s
- SSH host is required.
- Gateway token response missing access_token
- Gateway did not return a WS ticket.
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/ae302525eff3f346.
Report an issue: GitHub.