{"record":{"id":"b785a592abf875f2","repo":"kovidgoyal/kitty","slug":"line-decode-utf-8-replace-rstrip","errorCode":null,"errorMessage":"line.decode('utf-8', 'replace').rstrip()","messagePattern":"line\\.decode\\('utf-8', 'replace'\\)\\.rstrip\\(\\)","errorType":"console","errorClass":"SystemExit","httpStatus":null,"severity":"error","filePath":"shell-integration/ssh/bootstrap.py","lineNumber":185,"sourceCode":"        getattr(sys.stderr, 'buffer', sys.stderr).write(output)\n        raise SystemExit('Failed to compile the terminfo database')\n\n\ndef iter_base64_data(f):\n    global leading_data\n    started = 0\n    while True:\n        line = f.readline().rstrip()\n        if started == 0:\n            if line == b'KITTY_DATA_START':\n                started = 1\n            else:\n                leading_data += line\n        elif started == 1:\n            if line == b'OK':\n                started = 2\n            else:\n                raise SystemExit(line.decode('utf-8', 'replace').rstrip())\n        else:\n            if line == b'KITTY_DATA_END':\n                break\n            yield line\n\n\n@contextlib.contextmanager\ndef temporary_directory(dir, prefix):\n    # tempfile.TemporaryDirectory not available in python2\n    tdir = tempfile.mkdtemp(dir=dir, prefix=prefix)\n    try:\n        yield tdir\n    finally:\n        shutil.rmtree(tdir)\n\n\ndef get_data():\n    global data_dir, shell_integration_dir, leading_data","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/shell-integration/ssh/bootstrap.py#L167-L203","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before\nkitty +kitten ssh weirdhost\n# SystemExit: /bin/sh: base64: not found\n\n# after\n# install coreutils/busybox on the host, or:\nkitty +kitten ssh --shell-integration=disabled weirdhost","handlingStrategy":"fallback","validationCode":"import shutil\nok = shutil.which('base64') is not None and shutil.which('sh') is not None","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["kitty","ssh","shell-integration","handshake"],"backgroundTag":"remote-shell-handshake-failed","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}