PSA: send-keys silently truncates at 1024 bytes if the shell hasn't finished starting
Spent a day on this and there is no error message anywhere, so here it is.
tmux new -d -s "$s"
tmux send-keys -t "$s" '<long command>' C-m
This worked for months. Then the command I was sending grew past ~1200 bytes, and the pane started showing it chopped off mid-word, with the shell sitting at a continuation prompt waiting for a quote to close. tmux exits 0. The shell is happy. Nothing logs anything.
Right after new -d the shell hasn't finished starting, so the tty is still in canonical mode, and the kernel truncates a single line of canonical input at 1024 bytes (MAX_CANON). The overflow isn't an error. It's discarded.
Two ways out:
- Sleep before sending. Works. I sent ~1800 B two seconds later and it arrived intact. But you've traded a silent truncation for a race, and the race has no error message either.
- Shorten the line. I moved a conditional argument into positional parameters instead of branching into two command strings:
set --
[ -f "$catalog" ] && set -- -c "catalog=$catalog"
mycmd --flag "$@" "$id"
zsh and bash both fine, and "$@" expands to zero words when the file is missing. That took 1200 bytes down to a bit over 600.
Then I asserted on the length in a test, because this comes back the moment someone adds an argument. Assert on bytes, not characters: if your language counts UTF-16 code units, it will disagree with the kernel as soon as a path isn't ASCII.
Anyone know whether the limit is the same on Linux? I only hit this on macOS.