{"record":{"id":"c874f702d72fdc68","repo":"Eugeny/tabby","slug":"remote-rejected-opening-a-shell-channel-err","errorCode":null,"errorMessage":"Remote rejected opening a shell channel: ${err}","messagePattern":"Remote rejected opening a shell channel: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"tabby-ssh/src/session/shell.ts","lineNumber":48,"sourceCode":"    async start (): Promise<void> {\n        if (!this.ssh) {\n            throw new Error('SSH session not set')\n        }\n\n        this.ssh.ref()\n        this.ssh.willDestroy$.subscribe(() => {\n            this.destroy()\n        })\n\n        this.logger.debug('Opening shell')\n\n        try {\n            this.shell = await this.ssh.openShellChannel({ x11: this.profile.options.x11 })\n        } catch (err) {\n            if (err.toString().includes('Unable to request X11')) {\n                this.emitServiceMessage('    Make sure `xauth` is installed on the remote side')\n            }\n            throw new Error(`Remote rejected opening a shell channel: ${err}`)\n        }\n\n        this.open = true\n        this.logger.debug('Shell open')\n\n        this.loginScriptProcessor?.executeUnconditionalScripts()\n\n        this.shell.data$.subscribe(data => {\n            this.emitOutput(Buffer.from(data))\n        })\n\n        this.shell.eof$.subscribe(() => {\n            this.logger.info('Shell session ended')\n            if (this.open) {\n                this.destroy()\n            }\n        })\n    }","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/Eugeny/tabby/blob/14e2d60b9b6dee84a53c37f05eefeb803787de04/tabby-ssh/src/session/shell.ts#L30-L66","documentation":"Thrown by SSHShell when `ssh.openShellChannel({ x11 })` rejects - the remote SSH server refused to open an interactive shell channel. The original error is wrapped with a descriptive prefix; if the underlying error mentions X11, the user is additionally hinted to install `xauth` on the remote. Common when the server limits channels, the user has no shell, or pty allocation is denied.","triggerScenarios":"Calling `openShellChannel` against a server that rejects channel open: server-side `MaxSessions`/`MaxStartups` exceeded, the account has `nologin`/no shell, pty allocation denied by `sshd_config` (`PermitTTY no`), X11 forwarding requested but `X11Forwarding no` on the server, or the connection dropped mid-handshake.","commonSituations":"Reached per-user/session limit on a busy bastion; SFTP-only account used for a shell tab; X11 forwarding enabled in the profile but disabled on the server; flaky network caused the transport to die right before channel open.","solutions":["Reduce concurrent sessions on that host or raise server `MaxSessions`/`MaxStartups` if you administer it.","For an X11-related rejection, install `xauth` on the remote and enable `X11Forwarding yes`, or disable X11 in the profile (`options.x11 = false`).","Confirm the account has a valid shell (`/bin/bash`, not `/usr/sbin/nologin`) and `PermitTTY yes`.","Catch the error and retry once for transient transport drops; surface the wrapped remote message to the user for server-side fixes."],"exampleFix":"// before\ntry { this.shell = await this.ssh.openShellChannel({ x11: this.profile.options.x11 }) }\ncatch (err) { throw new Error(`Remote rejected opening a shell channel: ${err}`) }\n\n// after - retry without X11 if X11 was the cause\ntry {\n    this.shell = await this.ssh.openShellChannel({ x11: this.profile.options.x11 })\n} catch (err) {\n    if (this.profile.options.x11 && err.toString().includes('X11')) {\n        this.shell = await this.ssh.openShellChannel({ x11: false })\n    } else throw new Error(`Remote rejected opening a shell channel: ${err}`)\n}","handlingStrategy":"retry","validationCode":"function shouldRequestX11 (profile: SSHProfile, serverSupportsX11: boolean): boolean {\n    return Boolean(profile.options.x11) && serverSupportsX11\n}","typeGuard":null,"tryCatchPattern":"try {\n    this.shell = await this.ssh.openShellChannel({ x11: this.profile.options.x11 })\n} catch (err) {\n    const msg = err.toString()\n    if (this.profile.options.x11 && /X11/i.test(msg)) {\n        // retry without X11; server denied forwarding\n        this.shell = await this.ssh.openShellChannel({ x11: false })\n    } else {\n        throw new Error(`Remote rejected opening a shell channel: ${err}`)\n    }\n}","preventionTips":["Disable X11 in the profile if the server does not support it (PermitTTY/X11Forwarding).","Raise server MaxSessions/MaxStartups if you administer the host and hit limits.","Confirm the account has a valid shell and PermitTTY yes.","Retry once for transient transport drops; surface the wrapped remote message to the user."],"tags":["ssh","shell-channel","x11","server-config","network"],"backgroundTag":null,"analyzedSha":"14e2d60b9b6dee84a53c37f05eefeb803787de04","analyzedAt":"2026-08-12T11:46:48.773Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}