NousResearch/hermes-agent · error · Error
SshConnection requires a host.
Error message
SshConnection requires a host.
What it means
Constructor guard on SshConnection: the config object must exist and have a truthy host before any other validation or connection setup runs. It is the earliest possible failure for a malformed connection config — it fires before validateSshTarget, validateKeyPath, or control-path setup.
Source
Thrown at apps/desktop/electron/ssh-connection.ts:475
class SshConnection {
host: string
user: string
port: number
keyPath: string
controlPath: string
_spawnFn: any
_log: (msg: string) => void
_connectTimeoutMs: number
_execTimeoutMs: number
_forwardTimeoutMs: number
_opened: boolean
_mux: boolean
_tunnels: Map<string, any>
constructor(cfg, opts: any = {}) {
if (!cfg || !cfg.host) {
throw new Error('SshConnection requires a host.')
}
const port = cfg.port ? Number(cfg.port) : 22
validateSshTarget(cfg.host, cfg.user || '', port)
if (cfg.keyPath) {
validateKeyPath(cfg.keyPath)
}
this.host = cfg.host
this.user = cfg.user || ''
this.port = port
this.keyPath = cfg.keyPath || ''
// Windows OpenSSH has no ControlMaster (mux sockets were never implemented
// on Win32) — fall back to one ssh invocation per operation and a
// persistent `ssh -N -L` child per tunnel. Empty controlPath routes the
// pure builders onto their no-mux form.
this._mux = opts.mux ?? process.platform !== 'win32'View on GitHub (pinned to c896c09c42)
Solutions
- Ensure the config passed to SshConnection is a fully populated object with a non-empty host string.
- Check the persistence layer: the field written on save must be the field read on load (host).
- Guard call sites: skip connection attempts when the stored backend lacks a host and route the user back to remote setup.
Example fix
// before
const conn = new SshConnection(savedRemote)
// after
if (!savedRemote?.host) {
throw new TypeError('remote backend config is missing host; re-run remote setup')
}
const conn = new SshConnection(savedRemote) Defensive patterns
Strategy: type-guard
Validate before calling
if (!cfg || typeof cfg !== 'object' || typeof cfg.host !== 'string' || !cfg.host) {
throw new TypeError('SshConnection config must be an object with a non-empty host string')
} Type guard
function isSshConnectionConfig(cfg: unknown): cfg is { host: string; user?: string; port?: number | string; keyPath?: string } {
return Boolean(cfg && typeof cfg === 'object' && typeof (cfg as any).host === 'string' && (cfg as any).host.length > 0)
} Try / catch
try {
conn = new SshConnection(cfg)
} catch (e) {
if (e instanceof Error && e.message === 'SshConnection requires a host.') {
// config incomplete: route the user back to remote setup instead of crashing
openRemoteSetupDialog()
return null
}
throw e
} Prevention
- Validate deserialized remote configs before constructing connections.
- Fail fast on partial saves: mark config records complete only after all required fields are written.
- Centralize config shape checks in one loader so every call site is guarded.
When it happens
Trigger: new SshConnection(null), new SshConnection({}), or a config whose host field is missing/empty — e.g. deserializing a remote-backend entry that was never fully populated.
Common situations: Loading a saved remote backend whose JSON is missing the host key; passing a partially-built config object; a default-config factory returning {} before the user has filled anything in.
Related errors
- SSH host is required.
- SSH remote mode is selected but no host is configured.
- Remote path must not be empty.
- Unsafe SSH target: host is required.
- Unsafe SSH target: host must not start with a dash ("${host}
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/af6b5bc262d3f70d.
Report an issue: GitHub.