Simple job. Copy Videos folder from G4 over to JackSparrow2 with rsync. Done this a hundred times.

rsync -avP Videos/ tolga@100.xxx.xxx.xxx:/home/tolga/rsync/
protocol version mismatch, is your shell clean?
(see the rsync manpage for an explanation)
rsync error: protocol incompatibility (code 2) at compat.c(625) [sender=3.4.4]

Never seen that one before. Password prompt worked fine, so the connection itself was good. Something after that was the problem.

first thing i found

SSH’d in normally to have a look and there it was, plain as day. Every time I log into JackSparrow2 I get a full ASCII banner, box drawing characters, the works. Looks great for a normal login. But rsync uses SSH under the hood too, to spawn a remote process, and it does not want anything on that connection except rsync’s own protocol data. Any stray text before the handshake and it falls over exactly like this. So the banner was my first suspect. Went looking in /etc/motd, that’s the Cockpit and Jellyfin links box, not what was printing. Checked /etc/motd.d/, just a Cockpit symlink, nothing there either. Grepped for the actual banner text and found it in /etc/ssh/banner, being force fed on every single SSH connection through a Banner directive sitting in /etc/ssh/sshd_config.d/99-jacksparrow2.conf. That directive does not care whether the session is interactive or not, it just fires. Commented it out, restarted sshd. Ran the rsync again.

protocol version mismatch, is your shell clean?

Same error.

second thing i found

Went back into that same config file and PrintMotd yes was still sitting there, live, right above the Banner line I’d just killed. Commented that one out too, another sshd restart. Ran the rsync a third time. Still the exact same error. At this point I was starting to think it was something bigger, maybe a genuine rsync version mismatch between the two boxes, maybe something in the SSH multiplexing config. Checked both, nothing there. Went back to basics and just tried a plain SSH command instead of rsync, something with no banner logic attached at all.

ssh tolga@100.xxx.xxx.xxx "echo test"
If you want to program in C, program in C. It's a nice language. I
use it occasionally...  :-)
                -- Larry Wall in <7577@jpl-devvax.JPL.NASA.GOV>
test

There it was. A fortune cookie quote. Not the ASCII banner this time, a completely different thing, coming from somewhere else entirely, and it was still firing even with both sshd fixes in place. That confirmed the sshd side was actually clean now, this was something else altogether.

the actual culprit

grep -rn "fortune" ~/.bashrc
/home/tolga/.bashrc:27:echo " " && fortune | lolcat && echo " "

Line 27 of my own .bashrc. A fortune quote piped through lolcat, unconditionally, on every single shell that spins up, including the tiny non-interactive one rsync creates behind the scenes to run its remote process. Three completely separate things had been printing banners this whole time. SSH’s own Banner directive, PrintMotd, and now a fortune cookie sitting in my bashrc, all doing the same job of corrupting the handshake, from three different places. Wrapped the whole thing in an interactive shell check so it only fires for real logins:

case $- in
    *i*) ;;
      *) return ;;
esac

That guard goes at the very top of .bashrc, before anything decorative runs. If the shell isn’t interactive, bash just returns straight out of the file before it ever reaches the fortune line.

and then

rsync -avP ./ tolga@100.xxx.xxx.xxx:/home/tolga/rsync/
sending incremental file list
./
Actions Will Always Reveal The Truth.webm
        913,508 100%  279.98MB/s    0:00:00 (xfr#1, to-chk=21/23)
...
You Never Owned It Anyway.webm
        865,846 100%  781.47kB/s    0:00:01 (xfr#22, to-chk=0/23)

sent 23,844,147 bytes  received 437 bytes  1,445,126.30 bytes/sec
total size is 23,836,327  speedup is 1.00

Yes. Finally. Clean transfer, full speed, every file landed. Ran it a second time straight after just to check the incremental behaviour was working properly too, and it came back near instant since nothing had actually changed.

sent 1,151 bytes  received 12 bytes  258.44 bytes/sec
total size is 23,836,327  speedup is 20,495.55

Exactly what rsync’s supposed to do on a repeat run. Also learned something dumb along the way, the first rsync attempt after the fix failed for a different reason entirely, wrong path, because I was already sitting inside the Videos folder and told rsync to sync Videos/ again, which went looking for Videos inside Videos. Fixed that one by just pointing rsync at ./ instead since I was already standing in the right place. Three banners, one folder mixup, and one working transfer. If rsync or scp ever throws “protocol version mismatch, is your shell clean” at you, it means exactly what it says. Something is printing to the stream before the protocol handshake gets a chance to run. Check sshd’s Banner directive, check PrintMotd, and check your own shell rc files for anything that prints unconditionally, cowsay, fortune, neofetch, custom ASCII art, all of it. Any of them will do this. Mine had all three stacked on top of each other.