Eugeny/tabby · error · Error
Authentication rejected
Error message
Authentication rejected
What it means
Thrown by the SSH session after handleAuth() exhausts every configured authentication method (or detects a prior disconnect) and returns null. It is the terminal signal that the server rejected all offered credentials. Before throwing, the session disconnects the transport and deletes any stored password for the profile, so the stored credential is cleared on hard failure.
Source
Thrown at tabby-ssh/src/session/ssh.ts:484
if (this.authUsername?.startsWith('$')) {
try {
const result = process.env[this.authUsername.slice(1)]
this.authUsername = result ?? this.authUsername
} catch {
this.authUsername = 'root'
}
}
await this.populateStoredPasswordsForResolvedUsername()
const authenticatedClient = await this.handleAuth()
if (authenticatedClient) {
this.ssh = authenticatedClient
} else {
this.ssh.disconnect()
this.passwordStorage.deletePassword(this.profile, this.authUsername ?? undefined)
// eslint-disable-next-line @typescript-eslint/no-base-to-string
throw new Error('Authentication rejected')
}
// auth success
if (this.savedPassword) {
this.passwordStorage.savePassword(this.profile, this.savedPassword, this.authUsername ?? undefined)
}
for (const fw of this.profile.options.forwardedPorts) {
this.addPortForward(Object.assign(new ForwardedPort(), fw))
}
this.open = true
this.ssh.tcpChannelOpen$.subscribe(async event => {
this.logger.info(`Incoming forwarded connection: ${event.clientAddress}:${event.clientPort} -> ${event.targetAddress}:${event.targetPort}`)
if (!(this.ssh instanceof russh.AuthenticatedSSHClient)) {View on GitHub (pinned to 14e2d60b9b)
Solutions
- Verify credentials work with the OS openssh client: `ssh -v <user>@<host>` and compare the allowed auth methods it lists.
- In the profile, enable an auth method the server actually offers (check 'Auth methods' returned by the failed handshake); add a valid private key, or start ssh-agent and add the identity.
- Confirm the username is correct and not being mangled by the $ENV or prompt fallback (see authUsername resolution near ssh.ts:460).
- If using keyboard-interactive/2FA, ensure the prompts are answered and the server still offers the method after failures.
- Re-enter the password so a fresh one is saved, since the bad stored password was just deleted.
Example fix
// before: profile only has 'prompt-password' but server requires publickey // after: add a key-based method in the profile auth options, or load it into the agent ssh-add ~/.ssh/id_ed25519 // then in Tabby profile -> Credentials -> pick 'Private key' and select the key
Defensive patterns
Strategy: try-catch
Validate before calling
// Auth outcome cannot be pre-validated; verify config shape before starting.
const methods = profile.options.authMethods ?? []
if (methods.length === 0 && !profile.options.password && !profile.options.privateKey) {
throw new Error('No auth method configured; auth will be rejected')
} Try / catch
try {
await session.start()
} catch (e) {
if (e.message === 'Authentication rejected') {
// prompt user to fix credentials / add a key method, then retry start()
} else { throw e }
} Prevention
- Always configure at least one key-based auth method in addition to password.
- Test credentials with the OS ssh client before configuring the profile.
- Keep the SSH agent running with the identity loaded for publickey/agent auth.
When it happens
Trigger: Reached when this.handleAuth() (ssh.ts ~477) resolves to null. _handleAuth returns null when this.previouslyDisconnected is true, or when no remaining AuthMethod matches the server's allowed methods (methodsLeft). Concretely: every saved-password, prompt-password, publickey, keyboard-interactive, and agent attempt either returned an AuthFailure or threw, and no method is left to try.
Common situations: Wrong password / changed server password; private key no longer authorized in ~/.ssh/authorized_keys; server disabled 'password' auth and only allows 'publickey' but the user configured password-only; SSH agent not running or identity not loaded; account locked or AllowUsers/DenyUsers excludes the user; keyboard-interactive challenges answered incorrectly until the server stops offering methods.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- No username
- Cannot add remote port forward before auth
- Cannot remove remote port forward before auth
- Cannot open shell channel before auth
- ${method} ${url} failed: ${response.status} ${response.statu
AI-assisted analysis of Eugeny/tabby@14e2d60b9b (2026-08-12).
Data as JSON: /api/errors/ff941141706c1786.
Report an issue: GitHub.