Skip to content

stdin fed to a command that exits without reading it fails the run with WSManFault 232 #183

Description

@bertysentry

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.

Activity

  1. self-assigned this
    on Sep 27, 2026
  2. added a commit that references this issue on Sep 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions