Repository navigation
-c hangs instead of erroring when the command exceeds cmd.exe's line limit #3
Description
Activity
- added a commit that references this issue
on Sep 5, 2026 Correction to the framing above: this is not Windows-specific.
A
dashshell on a Linux agent truncates too — the tty line discipline cuts a canonical-mode read at 4094 characters, and the RC sentinel at the end of the line goes with it, exactly the same silent hang. Measured on a live Linux agent: 4094 passes, 4095 does not. It depends on the remote user's shell, not the OS: bash and zsh read the prompt line in raw mode and take a megabyte, while sh/dash/ash do not.Since the remote shell is not knowable in advance, the fix detects rather than predicts — see #4.
- added a commit that references this issue
on Sep 5, 2026 Reopening: the fix in #4 (released as v1.3.9) has been reverted, so the underlying problem stands.
The probe was not the passive observer it was meant to be. It is typed input, so a command that reads stdin consumes it before the shell does:
$ dwshell host -c "cat > /tmp/f" $ cat /tmp/f echo __DWSH_TRUNC_$?_END__Before the probe that command received nothing and waited out its timeout — irritating, but it left the user's data alone. After it, dwshell's own marker was written silently into the file. Trading a hang for quiet data corruption is worse than the problem being diagnosed, so
-cnow types the command and nothing else.The per-shell limits are documented in the README instead, so the symptom is recognisable: past the cap the remote truncates the line silently, the exit-code marker goes with it, and
-cwaits for output that never arrives.dwshell putplus running the script by path is the way around it.Leaving this open as a known limitation. Any future fix must not put anything into the stream the user's command could consume.
Closed with the timeout hint, which is as far as this can honestly go without touching what the user asked to run.
To record why nothing stronger shipped:
- Predicting the limit was tried and dropped. It differs by remote shell — roughly a megabyte with bash/zsh, 4094 characters under sh/dash/ash where the tty cuts a canonical-mode read, 8190 on cmd.exe — and the shell answering is not knowable in advance. A wrong prediction denies a command the remote would have run, which is worse than the hang.
- Detecting it was tried, shipped in v1.3.9 and reverted in v1.3.10. The probe was typed input, so any command reading stdin consumed it:
dwshell agent -c "cat > file"wrote dwshell's own marker into the file. Trading a hang for silent data corruption is the worse outcome. - Assembling the command across short lines works — verified under dash, a 100 KB command via
C="${C}"'chunk'pluseval— but it means escaping the user's command into shell string literals, and it would not lift the ceiling on Windows, where cmd.exe caps variables at 8191 too. Rejected as a rewrite out of proportion to the failure.
What shipped reads only what dwshell already has locally, the length of the line it sent and whether anything ran, and adds nothing to the wire.
Any future attempt has one hard constraint: it must not put anything into the stream the user's command could consume.
Split out of #1 (residual finding reported there after the v1.3.8 fix).
Summary
On a Windows agent, a
-ccommand whose wrapped line exceeds cmd.exe's limitmakes
dwshellwait for output that can never arrive: it burns the whole--timeoutand then reportsand with the default (no
--timeout) it waits forever. Nothing indicates thatthe length is the cause.
Mechanism
cmd.exe truncates a typed line past 8190 characters — verified against a
live Windows agent, 8190 passes and 8191 does not, deterministically.
The truncation is silent. Instrumenting the raw terminal stream over an
over-long line shows the
__DWSH_BEGIN__marker arriving and the prompt comingback, with no error text of any kind — the command is executed truncated, and
what gets cut off the end is exactly dwshell's
__DWSH_RC_%errorlevel%_END__sentinel.
dwshellthen waits for a marker that will never be sent.So there is no remote error message to surface here: cmd.exe emits none.
Fix
Reject the command up front, before connecting the shell, with a message that
names the limit and the way around it.