Repository navigation
Windows anonymous pipes do not work with createReadStream #57288
Description
Activity
After reading the nodejs source code for hours, I finally figured out the source of the problem!
Opening an anonymous pipe gives you a
HANDLEdirectly, not a file descriptor.However, UV (the dependency that handles various cross platform stuff for Node, like i/o) expects a an actual file descriptor, to be passed in
uv__get_osfhandlewhich calls_get_osfhandlewhich is meant to turn a file descriptor into aHANDLE.This of course doesn't work if you pass a
HANDLEinstead of a file descriptor, resulting in UV marking it as bad.The way to work around this would be to call
_open_osfhandleon theHANDLE, which does the opposite process, meaning it creates a file descriptor for a handle. Calling_get_osfhandleon the resulting file descriptor gives back the originalHANDLEvalue.This however doesn't seem to be possible to do with what we currently have: calling
_open_osfhandlefrom my parent program that generates the anonymous pipe will give a file descriptor that can only be used by said parent program. It cannot be inherited by child processes as far as I could find. And I cannot call it from the Node process without editing Node's code which is obviously not doable for production purposes.The solution would be for Node to directly allow inputting
HANDLEs, or have UV try to read the pipe as aHANDLEif it failed reading it as a file descriptor.ping @nodejs/libuv
The solution would be for Node to directly allow inputting
HANDLEsIIRC this is what we did for libuv v2...
It could be supported in v1.x by adding something like
uv_pipe_open_ex.uv_pipe_openliterally callsHANDLE os_handle = uv__get_osfhandle(file);on its first line, from there on down it operates exclusively on handles.Reacted by Saúl Ibarra CorretgéIt could be supported in v1.x by adding something like
uv_pipe_open_ex.uv_pipe_openliterally callsHANDLE os_handle = uv__get_osfhandle(file);on its first line, from there on down it operates exclusively on handles.This, with a way for either Node or UV to know which one to call depending of whatever was passed to be opened, would solve the issue.
Any idea on the doability and ETA of this? Would I need to make a PR (please no) or are there node / libuv contributors who usually solve this kind of issue?
Thx to all of you for your quick replies, by the way :)
Any idea on the doability and ETA of this? Would I need to make a PR (please no) or are there node / libuv contributors who usually solve this kind of issue?
Doability seems guaranteed, it's a matter of someone rolling up their sleeves and sending the PR. Since you are the interested party here a good way to see it through is to take matters in your own hands.
- addedstreamIssues and PRs related to Node.js streams.Issues and PRs related to Node.js streams.libuvIssues and PRs related to the libuv dependency or the uv binding.Issues and PRs related to the libuv dependency or the uv binding.
on Mar 13, 2025 github-actions commented
on Apr 20, 2026 on Apr 20, 2026 – with GitHub ActionsContributorMore actionsThis issue has been marked as stale due to 210 days of inactivity.
It will be automatically closed in 30 days if no further activity occurs. If this is still relevant, please leave a comment or update it to keep it open.- addedstaleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.Issues and PRs marked stale due to inactivity and scheduled for automatic closure.
on Apr 20, 2026 This issue has been marked as stale due to 210 days of inactivity. It will be automatically closed in 30 days if no further activity occurs. If this is still relevant, please leave a comment or update it to keep it open.
This is still relevant. I just don't have the required skills to fix it myself and make a PR.
- removedstaleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.Issues and PRs marked stale due to inactivity and scheduled for automatic closure.
on Apr 24, 2026 github-actions commented
on Jul 24, 2026 on Jul 24, 2026 – with GitHub ActionsContributorMore actionsThis issue has been marked as stale due to 90 days of inactivity.
It will be automatically closed in 30 days if no further activity occurs. If this is still relevant, please leave a comment or update it to keep it open.- addedstaleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.Issues and PRs marked stale due to inactivity and scheduled for automatic closure.
on Jul 24, 2026 This issue has been marked as stale due to 90 days of inactivity. It will be automatically closed in 30 days if no further activity occurs. If this is still relevant, please leave a comment or update it to keep it open.
This is still relevant as the PR associated with this issue (#63851) still hasn't been merged.
- removedstaleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.Issues and PRs marked stale due to inactivity and scheduled for automatic closure.
on Jul 26, 2026 - added a commit that references this issue
on Aug 6, 2026 - added a commit that references this issue
on Aug 6, 2026 - added a commit that references this issue
on Aug 13, 2026 - added 2 commits that reference this issue
on Aug 25, 2026
Version
Tested with 22.14.0 and 20.18.1
Platform
Subsystem
No response
What steps will reproduce the bug?
C# example for the anonymous pipe generator:
JS code that should be able to read and write from the pipes' file descriptors:
Source, should work according to the documentation and other examples I've seen.
How often does it reproduce? Is there a required condition?
Everytime I try to open an inherited anonymous pipe with NodeJS
What is the expected behavior? Why is that the expected behavior?
'data'events should be emitted when read pipes have new data, and it should be possible to send data to write pipes too.What do you see instead?
Whenever I bind a callback to a ReadStream created from a pipe's FD:
Whenever I try to write to a WriteStream created from a pipe's FD:
Additional information
The same Anonymous pipe generator C# program given as an example works well with C++ using the Windows API, so it's not a C# problem:
Of course, it also works with C# clients.