Environment: node-pty 1.1.0 · Windows 11 (26200) · ConPTY (useConpty: true, non-DLL path) · reproduced on Node 22.x
Description
On Windows, writing to a pty's stdin (conin) shortly after its child process has exited fails asynchronously with write EAGAIN. The write goes to WindowsPtyAgent._inSocket, which is created without any 'error' listener (windowsPtyAgent.js ~L82). The 'error' handler in windowsTerminal.js (L80) is attached to _socket = _agent.outSocket (the read side), not the write side. So the socket emits 'error' with no listener and the process throws:
Error: write EAGAIN
at WriteWrap.onWriteComplete [as oncomplete] (node:internal/stream_base_commons:87:19)
This is not catchable by the caller: IPty.write() returns normally and the failure surfaces later on the write-completion callback. IPty does not forward inSocket errors (_forwardEvents only wires _socket/outSocket), so a consumer cannot subscribe through the public API either.
Minimal repro (Node, no Electron)
const pty = require('node-pty')
const p = pty.spawn('cmd.exe', ['/k', 'echo hi'], { useConpty: true, cols: 80, rows: 24 })
setTimeout(() => { p.kill(); setTimeout(() => p.write('x'), 2000) }, 800)
// ~a couple seconds later: uncaught "write EAGAIN" from the inSocket
Timing-dependent: the conin pipe's 128 KB buffer stays writable briefly after death, then rejects with EAGAIN.
Expected
A write to a dead pty's stdin is dropped or surfaced as a catchable error — never an uncaught exception.
Suggested fix
Attach an 'error' handler to _inSocket (mirroring the outSocket handler), and/or forward its errors through IPty so consumers can handle them.
Downstream report
obogoni/playground#103
Environment: node-pty 1.1.0 · Windows 11 (26200) · ConPTY (
useConpty: true, non-DLL path) · reproduced on Node 22.xDescription
On Windows, writing to a pty's stdin (
conin) shortly after its child process has exited fails asynchronously withwrite EAGAIN. The write goes toWindowsPtyAgent._inSocket, which is created without any'error'listener (windowsPtyAgent.js~L82). The'error'handler inwindowsTerminal.js(L80) is attached to_socket = _agent.outSocket(the read side), not the write side. So the socket emits'error'with no listener and the process throws:This is not catchable by the caller:
IPty.write()returns normally and the failure surfaces later on the write-completion callback.IPtydoes not forwardinSocketerrors (_forwardEventsonly wires_socket/outSocket), so a consumer cannot subscribe through the public API either.Minimal repro (Node, no Electron)
Timing-dependent: the conin pipe's 128 KB buffer stays writable briefly after death, then rejects with
EAGAIN.Expected
A write to a dead pty's stdin is dropped or surfaced as a catchable error — never an uncaught exception.
Suggested fix
Attach an
'error'handler to_inSocket(mirroring the outSocket handler), and/or forward its errors throughIPtyso consumers can handle them.Downstream report
obogoni/playground#103