Eugeny/tabby · error · Error

No username

Error message

No username

What it means

Thrown at the top of the private _handleAuth() when this.authUsername is falsy. russh requires a username for every authenticate* call, so the session refuses to proceed without one. The username is resolved earlier from the profile, an interactive prompt, or a $ENV-variable reference, so reaching here means all of those failed to produce a value.

Source

Thrown at tabby-ssh/src/session/ssh.ts:644

            }
        })
        try {
            return await this._handleAuth()
        } finally {
            subscription.unsubscribe()
        }
    }

    // eslint-disable-next-line max-statements
    private async _handleAuth (): Promise<russh.AuthenticatedSSHClient|null> {
        this.activePrivateKey = null

        if (!(this.ssh instanceof russh.SSHClient)) {
            throw new Error('Wrong state for auth handling')
        }

        if (!this.authUsername) {
            throw new Error('No username')
        }

        const noneResult = await this.ssh.authenticateNone(this.authUsername)
        if (noneResult instanceof russh.AuthenticatedSSHClient) {
            return noneResult
        }

        let remainingMethods = [...this.allAuthMethods]
        let methodsLeft = noneResult.remainingMethods

        function maybeSetRemainingMethods (r: russh.AuthFailure) {
            if (r.remainingMethods.length) {
                methodsLeft = r.remainingMethods
            }
        }

        while (true) {
            const m = methodsLeft

View on GitHub (pinned to 14e2d60b9b)

Solutions

  1. Set the 'User' field on the SSH profile (profile.options.user) before connecting.
  2. If using a $ENV reference, ensure that environment variable is exported and non-empty in the process running Tabby.
  3. Provide a username in the connect string (user@host) when creating the profile.
  4. Catch the prompt cancellation upstream and fall back to a sane default like the OS username or 'root'.

Example fix

// before: profile.options.user = ''
// after
profile.options.user = process.env.USER || 'root'
Defensive patterns

Strategy: validation

Validate before calling

if (!profile.options.user && !(profile.options.user ?? '').startsWith('$')) {
    throw new Error('SSH profile is missing a username')
}
// if using $ENV:
if ((profile.options.user ?? '').startsWith('$')) {
    const v = process.env[profile.options.user.slice(1)]
    if (!v) throw new Error(`Referenced env var ${profile.options.user} is empty`)
}

Prevention

When it happens

Trigger: this.authUsername is null/empty at ssh.ts:643. That happens when the profile has no user set, the username prompt (PromptModalComponent) was dismissed/cancelled, and the env-var fallback ($VAR) resolved to empty. _handleAuth is called from handleAuth (ssh.ts:477) during the main start() flow.

Common situations: New SSH profile with the 'User' field left blank and the user dismisses the username prompt; profile user set to '$FOO' but that environment variable is unset/empty; profile imported from a URL/host without a user component and defaults failed.

Related errors


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