NousResearch/hermes-agent · error · Error
SSH remote mode is selected but no host is configured.
Error message
SSH remote mode is selected but no host is configured.
What it means
Thrown while resolving the desktop app's backend connection when the saved connection config has mode 'ssh' but normalizeSshConfig() cannot produce a usable SSH config — in practice because no host was set. It is a startup-time configuration validation error from the Electron main process connection resolver, not a network failure. The app refuses to guess a host, so boot stops until the SSH settings are completed or the mode is changed.
Source
Thrown at apps/desktop/electron/main.ts:7581
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)
return bootstrapSshConnection(null, ssh, reuseToken, 'settings')
}
// Cloud resolves through the existing URL/OAuth path.
if (!modeIsRemoteLike(config.mode)) {
return null
}
const authMode = normAuthMode(config.remote?.authMode)
const token = authMode === 'oauth' ? null : decryptDesktopSecret(config.remote?.token)
return buildRemoteConnection(
config.remote?.url,
authMode,View on GitHub (pinned to c896c09c42)
Solutions
- Open the desktop app's connection settings and enter the SSH host (and user/port if needed) for the SSH remote, then reconnect
- If SSH was never intended, switch the connection mode back to 'local' or 'remote URL' and save
- Inspect the saved desktop connection config for the profile and fix the mode/remote.host mismatch by hand
- Verify normalizeSshConfig's required fields (host) against what the settings UI persists before filing a bug
Example fix
// before (saved config)
{ "mode": "ssh", "remote": { "user": "me" } }
// after
{ "mode": "ssh", "remote": { "host": "box.example.com", "user": "me", "port": 22 } } Defensive patterns
Strategy: validation
Validate before calling
// Before starting SSH connection resolution
const cfg = readDesktopConnectionConfig()
if (cfg.mode === 'ssh' && !(cfg.remote?.host ?? '').trim()) {
throw new Error('Complete SSH settings (host) before connecting in SSH mode')
} Type guard
function hasUsableSshRemote(cfg: { mode?: string; remote?: { host?: string } | null }): boolean {
return cfg.mode === 'ssh' && typeof cfg.remote?.host === 'string' && cfg.remote.host.trim().length > 0
} Try / catch
catch (e) { if (e instanceof Error && e.message.includes('SSH remote mode')) { promptUserForSshHost() } else { throw e } } Prevention
- Disable the connect/save action in the settings UI until SSH host is non-empty when mode is ssh
- Never hand-edit mode to 'ssh' without also writing remote.host
- Show the effective SSH config summary before connecting so an empty host is visible
When it happens
Trigger: Desktop connection settings (or the underlying config file) specify mode: 'ssh' with an empty/missing remote.host, or remote is absent entirely; the resolver reaches the 'if (config.mode === \'ssh\')' branch and normalizeSshConfig({mode:'ssh', ...config.remote}) returns null.
Common situations: User switches the connection mode dropdown to SSH in settings but saves before entering a host; a config migration or hand-edited config file drops the remote block; a profile reset leaves mode='ssh' with stale empty remote settings.
Related errors
- SSH host is required.
- Branch name is required.
- Hermes install at ${ACTIVE_HERMES_ROOT} is missing or incomp
- Git for Windows is required for Hermes on Windows (provides
- Hermes venv missing at ${VENV_ROOT}. Re-run the desktop inst
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/c91c115723551b56.
Report an issue: GitHub.