Windows: conin socket has no 'error' listener, so a failed pty write is an uncaught exception
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 76/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Quiet
- Tech stack
- node.js, typescript
- Domain
- operating-systems
Research direction
Start in windowsPtyAgent.js:79, where conin creates _inSocket, and compare it with the conout error handling in windowsTerminal.js:54 and :90. Trace the write and cleanup paths at windowsTerminal.js:123 and windowsPtyAgent.js:176, then add coverage for failed writes or destruction during a write on Windows. Done means conin errors no longer become uncaught process exceptions and existing exit or close behavior remains intact.
Written by the indexing model from the issue text.
Description
Summary
On Windows, the conin (write side) socket is constructed without an 'error' listener, so any write failure on it becomes an uncaught exception and takes down the host process. The conout (read side) socket does get one.
Observed as Error: write EAGAIN (errno: -4088) escaping as an uncaught exception, with no 'error' event available on anything the embedder owns.
Version: 1.2.0-beta.14 (line references below are from the published lib/, and match the compiled output 1:1).
The asymmetry
conout gets a listener — windowsTerminal.js:54 assigns it and :90 attaches the handler:
this._socket = this._agent.outSocket;
// ...
this._socket.on('error', (err) => { /* ... */ });
conin does not. windowsPtyAgent.js:79:
const inSocketFD = fs.openSync(term.conin, 'w');
this._inSocket = new net.Socket({ fd: inSocketFD, readable: false, writable: true });
this._inSocket.setEncoding('utf8');
Grepping the package, _inSocket never receives an 'error' handler anywhere.
Why that is load-bearing
_inSocket is the write path — windowsTerminal.js:123:
this._agent.inSocket.write(data);
and kill() destroys it — windowsPtyAgent.js:176:
this._inSocket.destroy();
A net.Socket with no 'error' listener re-throws on error, so both of these can crash the process:
- backpressure — EAGAIN when conin's buffer fills under sustained input
- a write racing
kill()— the socket is destroyed while a write is in flight
Because the throw originates inside node-pty's own plumbing, an embedder cannot prevent it. Terminal.on() forwards to the conout socket, so there is no public route to conin; the only workaround is reaching through the private _agent to inSocket and attaching the listener from outside, which is what we currently do.
Suggested fix
Attach a handler where the socket is created, mirroring the conout side — even a no-op prevents the process-level throw and lets the existing exit/close paths drive the lifecycle:
this._inSocket.on('error', () => { /* surfaced via onExit / the existing error path */ });
Routing it through _onError for parity with conout would be better still, if that suits the intended semantics.
Impact
For anything long-lived that writes to a pty and kills ptys on demand — terminal multiplexers, session managers, agent supervisors — this is a hard crash of the host process on Windows rather than a recoverable error. It presents as an intermittent uncaught exception attributed to whatever code happened to be running, which makes it easy to misfile as unrelated flakiness.
Happy to open a PR if the one-line form above is acceptable.
- Dominant language
- TypeScript
- Stars
- 2k
- Forks
- 337
- Avg merge
- 21h 58m
- Merged PRs (30d)
- 3
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from microsoft/node-pty
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
All issues in microsoft/node-pty
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
Eynzof/Hermes-CN-Desktop#610 ·
-
bug clawsweeper:linked-pr-open clawsweeper:needs-live-repro clawsweeper:no-new-fix-pr impact:message-loss issue-rating: 🐚 platinum hermit P2 regression
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
calcite-components needs triage refactor
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Esri/calcite-design-system#15203 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 90/100
danielmiessler/LifeOS#2218 ·