Repository navigation
Discard stdin a command does not read instead of failing on WSManFault 232 (#183) - #185
Merged
bertysentry merged 1 commit intoSep 28, 2026
Conversation
…t 232 (#183) A Send answered with WSManFault 232 ("The pipe is being closed") means the command exited, or closed its stdin, before its input arrived. The client turned that race into a WinRMFaultException and lost the command's output and exit code: execute() and start() failed whenever stdin(...) fed a command that does not read it (every time on Windows Server 2008 R2, now and then on 2016 and 2022), and so did the CLI when input was piped into such a command. RemoteCommand.send now treats that fault like a broken pipe: it stops sending, discards the rest of the input, and the Receive loop goes on, so the caller gets the actual output and exit code. Any other fault still fails. Every stdin path goes through it: pre-supplied input with execute() and start(), and RemoteProcess.stdin(), whose flush() and close() stay silent for input the command does not read, because whether that input beats the command's exit varies from host to host. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
bertysentry
deleted the
183-stdin-fed-to-a-command-that-exits-without-reading-it-fails-the-run-with-wsmanfault-232
branch
September 28, 2026 14:59
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #183.
Problem
When a command exits without reading its standard input, or before the input arrives, the server answers the WSMan
Sendwith fault 232, "The pipe is being closed".WsmanClient.RemoteCommand.send(...)turned it into aWinRMFaultException, soexecute()andstart()failed and lost the command's output and exit code. The CLI failed the same way whenever input was piped into such a command (echo x | … exec hostname, exit 70).Fix
RemoteCommand.send(...)treats fault 232 like a broken pipe on a localjava.lang.Process: it stops sending, discards the rest of the input, and the Receive loop goes on, so the caller gets the command's actual output and exit code. Any other fault still fails.Every stdin path goes through that method, so the fix covers them all:
stdin(String|Path|InputStream)) withexecute()andstart();RemoteProcess.stdin():flush()andclose()stay silent for input the command does not read. AProcesspipe would throw anIOExceptionhere, but whether the input beats the command's exit varies from host to host (every time on 2008 R2, never in five runs on 2019), and a failure would too. The output and exit code tell the caller how the command went.The CLI's interactive
shellpump also writes throughRemoteProcess.stdin(). Input it sends after the remotecmd.exeexited should therefore no longer fail the session. That follows from the code path; I didn't reproduce it live, because the timing window is narrow there.Tests
Four new
FakeWsmanServertests inCommandStdinTest:execute(), where the first of three read buffers is refused with fault 232: the output and exit code are returned, and nothing more is sent;start()with pre-supplied input, refused the same way;RemoteProcess.stdin(): the refusedflush(), a later write andclose()don't fail and send nothing more, and the output and exit code (1) are read normally;Sendstill failsexecute()with aWinRMFaultException.Without the fix, the three fault-232 tests fail with
Send failed: HTTP 500 (WSManFault 232): The pipe is being closed.mvn clean verify sitepasses.Live check:
anaxagore, Windows Server 2008 R2echo x | java -cp target/classes org.metricshub.winrm.cli.WinRmCli -h anaxagore … exec hostnameprintedwinrm-java: Send failed: HTTP 500 (WSManFault 232): The pipe is being closed.and exited 70.ANAXAGOREand exit 0.stdin("x\n").execute()andstdin("x\n").start()both returnANAXAGOREwith exit code 0.RemoteProcess.stdin()3 s aftercmd /c echo early& exit 3exited doesn't fail, andearlyand exit code 3 are reported.hostnamecompletes in 124 ms.sortstill gets its input.Docs
commands.md, and the stdin forwarding paragraph ofcli.md: input the command does not read is discarded.CommandRequest.stdin(String)(which the otherstdin(...)variants refer to),RemoteProcess.stdin()andCommandCursor.send(...).Known limit
After the refusal, pre-supplied input from a stream is still read to its end, although nothing more is sent. An endless producer (
yes | … exec hostname) therefore runs until the timeout. Stopping the read would requireCommandCursor.send(...)to report the refusal, which changes a public interface released since 2.0.00, so it is left out.🤖 Generated with Claude Code