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

  1. Set both variables together: export HERMES_DESKTOP_REMOTE_URL=... and export HERMES_DESKTOP_REMOTE_TOKEN=...
  2. Unset HERMES_DESKTOP_REMOTE_URL if you intend to use the in-app Settings → Gateway configuration instead.
  3. 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

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


AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14). Data as JSON: /api/errors/ae302525eff3f346. Report an issue: GitHub.