#2389·rtk

rtk err re-splits child command argv on whitespace — quoted arguments corrupted, exit codes silently wrong

Author: disi-omniCreated Jun 11, 2026Updated Sep 16, 2026
Labelsbuggood first issuepriority:higharea:cli

Version: rtk 0.42.3 (macOS arm64, Homebrew)

rtk err does not preserve the argv vector of its child command. The trailing [COMMAND]... args are flattened and re-split on whitespace, so any single quoted argument containing a space is split into multiple arguments. rtk proxy preserves argv correctly, which isolates the defect to the err path.

Minimal repro (argv inspection):

cat > /tmp/argspy <<'EOF'
#!/bin/sh
printf 'argc=%s\n' "$#"
for a in "$@"; do printf 'arg=[%s]\n' "$a"; done
EOF
chmod +x /tmp/argspy

$ rtk err /tmp/argspy 'a b' c
argc=3
arg=[a]
arg=[b]          # ← 'a b' was split
arg=[c]

$ rtk proxy /tmp/argspy 'a b' c
argc=2
arg=[a b]        # ← correct
arg=[c]

Observable consequence — exit code silently wrong:

$ rtk err sh -c 'exit 7'; echo "exit:$?"
[ok] Command completed successfully (no errors)
exit:0           # ← expected 7

$ rtk err -- sh -c 'exit 7'; echo "exit:$?"
[ok] Command completed successfully (no errors)
exit:0           # ← `--` does not help

$ printf '#!/bin/sh\nexit 7\n' > /tmp/exit7.sh; chmod +x /tmp/exit7.sh
$ rtk err /tmp/exit7.sh; echo "exit:$?"
[FAIL] Command failed (exit code: 7)
exit:7           # ← a flagless command works correctly

Mechanism: rtk err sh -c 'exit 7' reaches sh as sh -c exit 7 (the quoted exit 7 re-split into exit + 7). Per POSIX, sh -c exit 7 runs the one-word script exit with $0=7, which exits 0 — so the real failure is masked. Confirmed independently: plain sh -c exit 7 → 0, sh -c 'exit 7' → 7.

Impact: any rtk err <cmd> whose child takes a quoted argument containing whitespace — sh -c '…', bash -c '…', make -C 'dir with space', node -e 'a; b' — runs a corrupted command. Because err reports status from the (wrong) child, hard failures can be reported as success.

Expected: rtk err should pass the child argv through verbatim, exactly as rtk proxy does.