Eugeny/tabby · error · Error

${profile.options.host}: jump host "${profile.options.jumpHo

Error message

${profile.options.host}: jump host "${profile.options.jumpHost}" not found in your config

What it means

Thrown during SSH session setup when `profile.options.jumpHost` references a profile id that is not present in the loaded profiles list. The jump host is resolved by id (`profiles.find(x => x.id === jumpHost)`); a missing id means the proxy chain cannot be constructed, so connection is aborted before any socket is opened.

Source

Thrown at tabby-ssh/src/components/sshTab.component.ts:85

                case 'open-sftp':
                    this.openSFTP()
                    break
            }
        })

        super.ngOnInit()
    }

    async setupOneSession (injector: Injector, profile: SSHProfile, multiplex = true): Promise<SSHSession> {
        let session = await this.sshMultiplexer.getSession(profile)
        if (!multiplex || !session || !profile.options.reuseSession) {
            session = new SSHSession(injector, profile)

            if (profile.options.jumpHost) {
                const jumpConnection = (await this.profilesService.getProfiles()).find(x => x.id === profile.options.jumpHost)

                if (!jumpConnection) {
                    throw new Error(`${profile.options.host}: jump host "${profile.options.jumpHost}" not found in your config`)
                }

                const jumpSession = await this.setupOneSession(
                    this.injector,
                    this.profilesService.getConfigProxyForProfile<SSHProfile>(jumpConnection),
                )

                jumpSession.ref()
                session.willDestroy$.subscribe(() => jumpSession.unref())
                jumpSession.willDestroy$.subscribe(() => {
                    if (session?.open) {
                        session.destroy()
                    }
                })

                if (!(jumpSession.ssh instanceof russh.AuthenticatedSSHClient)) {
                    throw new Error('Jump session is not authenticated yet somehow')
                }

View on GitHub (pinned to 14e2d60b9b)

Solutions

  1. Open the profile settings and re-pick the jump host from the dropdown so the correct id is stored, or clear the jumpHost field.
  2. If the jump host profile was deleted, recreate it and re-select it, or remove the jumpHost reference.
  3. Validate profile integrity at config load: scan for jumpHost ids that no longer resolve and warn the user.
  4. Check that config-sync delivered the complete set of profiles (the jump host must be synced alongside its dependents).

Example fix

// before
if (!jumpConnection) throw new Error(`${profile.options.host}: jump host "${profile.options.jumpHost}" not found in your config`)

// after - validate references at config load and surface a list of candidates
const all = await this.profilesService.getProfiles()
const jumpConnection = all.find(x => x.id === profile.options.jumpHost)
if (!jumpConnection) {
    const suggestions = all.filter(x => (x.options as any)?.host === profile.options.host).map(x => x.id)
    throw new Error(`Jump host id "${profile.options.jumpHost}" not found. Did you mean: ${suggestions.join(', ') || '(no candidates)'}`)
}
Defensive patterns

Strategy: validation

Validate before calling

async function jumpHostExists (profilesService: ProfilesService, jumpId: string | undefined): Promise<boolean> {
    if (!jumpId) return true
    const all = await profilesService.getProfiles()
    return all.some(p => p.id === jumpId)
}

if (!await jumpHostExists(this.profilesService, profile.options.jumpHost)) {
    throw new Error(`Jump host ${profile.options.jumpHost} not found; pick a valid profile or clear it`)
}

Type guard

function hasValidJumpHost (profile: SSHProfile, all: Profile[]): boolean {
    return !profile.options.jumpHost || all.some(p => p.id === profile.options.jumpHost)
}

Try / catch

try {
    session = await this.setupOneSession(injector, profile)
} catch (e) {
    if (e instanceof Error && /jump host .* not found/.test(e.message)) {
        // prompt user to re-pick or clear jumpHost, then retry
        return
    }
    throw e
}

Prevention

When it happens

Trigger: An SSH profile has `options.jumpHost = '<id>'` but no profile with that id exists in config. Occurs after the jump-host profile was deleted/renamed, after a config-sync that omitted it, or when the id was typed manually and is wrong.

Common situations: User deleted or renamed the jump/bastion profile but left references to it; config imported from another machine without the jump host; typo in the id; profile id changed after a migration.

Related errors


AI-assisted analysis of Eugeny/tabby@14e2d60b9b (2026-08-12). Data as JSON: /api/errors/17155bc31a34c238. Report an issue: GitHub.