kovidgoyal/kitty · error · SystemExit
line.decode('utf-8', 'replace').rstrip()
Error message
line.decode('utf-8', 'replace').rstrip() What it means
Raised by iter_base64_data() in kitty's SSH bootstrap when, during the base64 handshake that transfers files/data to the remote host, a line other than b'OK' arrives after the start marker. The remote shell was expected to acknowledge with OK; instead it emitted something else, so the script surfaces that decoded line as the error message via SystemExit. The message content is whatever the remote side printed.
Solutions
- Read the message text — it is literally the remote host's output and names the real problem
- Ensure the remote login shell is POSIX-compatible and that base64 exists on the host
- Silence startup noise on the remote host (avoid echo/printf in .bashrc for non-interactive sessions)
- Try `kitty +kitten ssh user@host --shell-integration=disabled` (or a plain ssh) to confirm the host itself works, then re-enable
Example fix
# before kitty +kitten ssh weirdhost # SystemExit: /bin/sh: base64: not found # after # install coreutils/busybox on the host, or: kitty +kitten ssh --shell-integration=disabled weirdhost
Defensive patterns
Strategy: fallback
Validate before calling
import shutil
ok = shutil.which('base64') is not None and shutil.which('sh') is not None Prevention
- Make remote shell startup files quiet for non-interactive sessions
- Verify base64 and a POSIX shell exist on target hosts before using kitty ssh integration
- Test problematic hosts with --shell-integration=disabled to isolate handshake issues
When it happens
Trigger: kitty ssh bootstrap sends a POSIX-shell/base64 payload to the remote host; if the remote shell prints a warning/error (e.g. 'base64: not found', a shell error, or a login banner in the wrong place) before acknowledging OK, this SystemExit fires with that text.
Common situations: Remote hosts lacking base64 or with a non-POSIX shell; shell startup files (.bashrc/.profile) printing output that corrupts the handshake; hosts with forced motd/login scripts interleaving output; ancient busybox shells with nonstandard behavior.
Related errors
- Bad config lines: with error
- Cannot forward kitty remote control socket when an abstract…
- Cannot use forward_remote_control=yes without…
- Failed to compile the terminfo database
- Failed to open controlling terminal with error
AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27).
Data as JSON: /api/errors/b785a592abf875f2.
Report an issue: GitHub.
Appendix: source
Thrown at shell-integration/ssh/bootstrap.py:185
getattr(sys.stderr, 'buffer', sys.stderr).write(output)
raise SystemExit('Failed to compile the terminfo database')
def iter_base64_data(f):
global leading_data
started = 0
while True:
line = f.readline().rstrip()
if started == 0:
if line == b'KITTY_DATA_START':
started = 1
else:
leading_data += line
elif started == 1:
if line == b'OK':
started = 2
else:
raise SystemExit(line.decode('utf-8', 'replace').rstrip())
else:
if line == b'KITTY_DATA_END':
break
yield line
@contextlib.contextmanager
def temporary_directory(dir, prefix):
# tempfile.TemporaryDirectory not available in python2
tdir = tempfile.mkdtemp(dir=dir, prefix=prefix)
try:
yield tdir
finally:
shutil.rmtree(tdir)
def get_data():
global data_dir, shell_integration_dir, leading_dataView on GitHub (pinned to 6d5d0c4406)