Found while live-testing #139.
Problem
When a command gets standard input but exits without reading it, or exits before the input arrives, the server rejects the WSMan Send carrying that input with fault 232, "The pipe is being closed". The client lets that fault end the whole execution: it throws a WinRMFaultException, and the command's output and exit code are lost, although the command itself ran fine.
Through the API:
client.command("hostname").stdin("x\n").execute();
// WinRMFaultException: Send failed: HTTP 500 (WSManFault 232): The pipe is being closed.
The CLI forwards piped standard input automatically, so piping anything into a command that ignores its input can hit it:
echo x | java -jar winrm-java-standalone.jar -h server -u user -pf pw.txt exec hostname
# winrm-java: Send failed: HTTP 500 (WSManFault 232): The pipe is being closed.
# exit code 70, and the host name is never printed
Measured
It is a race between the remote process exiting and the Send reaching the server, so how often it hits depends on the host (2026-09-28):
| Windows |
CLI, piped input |
API, stdin("x\n").execute() |
| Server 2008 R2 |
3 of 3 runs failed |
4 of 4 runs failed |
| Server 2016 |
3 of 6 runs failed |
0 of 6 runs failed |
| Server 2019 |
0 of 5 runs failed |
not run |
| Server 2022, French |
1 of 5 runs failed |
not run |
The French host reports the same fault as « Le canal de communication est sur le point d'être fermé ». None of the few runs with empty input (< /dev/null), which sends only the end-of-input marker, failed.
Expected
Treat it like a broken pipe on a local java.lang.Process: a Send rejected with fault 232 means the remote process no longer reads its input. Stop sending, discard the rest of the input, and keep receiving, so the caller gets the command's actual output and exit code. Any other fault keeps failing as it does today.
Where
WsmanClient.RemoteCommand.send(...) turns the fault into a WinRMFaultException.
CommandRequest.feedStdin(...) lets it escape from execute(), which closes the cursor before the output is drained. start() fails the same way when stdin(...) pre-supplies the input.
RemoteProcess.stdin(): decide whether flush() and close() should swallow the fault or report it, the way Process.getOutputStream() reports a broken pipe with an IOException. RemoteProcess already ignores a lone end-of-input once the command has completed.
Tests and docs
- A
FakeWsmanServer test that answers the Send with fault 232, then a Receive carrying output and Done: execute() must return that output and the exit code. It should fail without the fix.
- The same scenario through
start().
- A live check on a Server 2008 R2 host, where it currently fails every time.
- The "Standard input" section of
commands.md should say that input the command does not read is discarded.
Found while live-testing #139.
Problem
When a command gets standard input but exits without reading it, or exits before the input arrives, the server rejects the WSMan
Sendcarrying that input with fault 232, "The pipe is being closed". The client lets that fault end the whole execution: it throws aWinRMFaultException, and the command's output and exit code are lost, although the command itself ran fine.Through the API:
The CLI forwards piped standard input automatically, so piping anything into a command that ignores its input can hit it:
Measured
It is a race between the remote process exiting and the
Sendreaching the server, so how often it hits depends on the host (2026-09-28):stdin("x\n").execute()The French host reports the same fault as « Le canal de communication est sur le point d'être fermé ». None of the few runs with empty input (
< /dev/null), which sends only the end-of-input marker, failed.Expected
Treat it like a broken pipe on a local
java.lang.Process: aSendrejected with fault 232 means the remote process no longer reads its input. Stop sending, discard the rest of the input, and keep receiving, so the caller gets the command's actual output and exit code. Any other fault keeps failing as it does today.Where
WsmanClient.RemoteCommand.send(...)turns the fault into aWinRMFaultException.CommandRequest.feedStdin(...)lets it escape fromexecute(), which closes the cursor before the output is drained.start()fails the same way whenstdin(...)pre-supplies the input.RemoteProcess.stdin(): decide whetherflush()andclose()should swallow the fault or report it, the wayProcess.getOutputStream()reports a broken pipe with anIOException.RemoteProcessalready ignores a lone end-of-input once the command has completed.Tests and docs
FakeWsmanServertest that answers theSendwith fault 232, then aReceivecarrying output andDone:execute()must return that output and the exit code. It should fail without the fix.start().commands.mdshould say that input the command does not read is discarded.