Repository navigation
Unhandled Exception in readline interface #58289
Description
Activity
It'd be useful that you paste a error stack trace.
You haven't answered the "Why is that the expected behavior?" question, IMO if the read stream fails to close is different from the readline failing to close, you should listed to the
'error'and/or'close'even of the read stream.Hi, this is not a bug per-se; you should be listening to the stream errors, not the readline errors. The readline is not failing, it is your stream.
import { once } from 'events' import { createReadStream } from 'fs' import { createInterface } from 'readline' let position = 0 const myDummyFilesystem = { read: (fd, buffer, offset, len, pos, cb) => { buffer.write("A\n"); cb(null, ((position += 2) <= 10) ? 2 : 0, buffer) }, close: (x, cb) => { cb(new Error("close failed")) }, open: (name, flags, mode, cb) => { cb(undefined, 42) } } async function bad() { const file = createReadStream('app.js', { fs: myDummyFilesystem }) const rl = createInterface({ input: file }) let lineNr = 0 rl.on('line', (line) => console.log(`bad ${++lineNr} ${line}`)) await once(file, 'close') // NOW DOES CATCH Error of the fs.close() CALL } async function good() { const file = createReadStream('app.js', { fs: myDummyFilesystem }) let lineNr = 0 file.on('data', (line) => console.log(`good ..`)) await once(file, 'close') // CATCHES Error of the fs.close() CALL } await (good().catch(e => console.error("nice first catch", e))) position = 0 bad().catch(e => console.error("nice second catch", e))
You could consider that snippet as a solution for this. But this may raise some discussion around what events we listen to from the backing stream in readline.
cc // @nodejs/streams
If i fail in the the fs.read() call instead of the fs.close() call, the error is caught by the readline interface with
await once(rl, 'close').I would expect that i either need to handle all input stream errors on my own, or that the readline interface provides an wrapper that abstracts/forwards all errors of the input stream.
Output with read errors:
node nodeError2.js nice first catch v23.11.0 Error: read failed at file:///Users/js/readline/nodeError2.js:8:17 at ModuleJob.run (node:internal/modules/esm/module_job:274:25) at async onImport.tracePromise.__proto__ (node:internal/modules/esm/loader:644:26) at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:98:5) . . . . . node:events:485 throw er; // Unhandled 'error' event ^ Error: close failed at file:///Users/js/readline/nodeError2.js:27:14 at process.processTicksAndRejections (node:internal/process/task_queues:105:5) Emitted 'error' event on ReadStream instance at: at emitErrorNT (node:internal/streams/destroy:170:8) at emitErrorCloseNT (node:internal/streams/destroy:129:3) at process.processTicksAndRejections (node:internal/process/task_queues:90:21)new Code with read error:
import { once } from 'events' import { createReadStream } from 'fs' import { createInterface } from 'readline' let readError = new Error("read failed") let closeError = null let position = 0 const myDummyFilesystem = { read: (fd, buffer, offset, len, pos, cb) => { buffer.write("A\n"); cb(readError, ((position += 2) <= 10) ? 2 : 0, buffer) }, close: (x, cb) => { cb(closeError) }, open: (name, flags, mode, cb) => { cb(undefined, 42) } } async function fun() { const file = createReadStream('app.js', { fs: myDummyFilesystem }) const rl = createInterface({ input: file }) let lineNr = 0 rl.on('line', (line) => console.log(`.`)) await once(rl, 'close') // DOES NOT CATCH Error of the fs.close() CALL } await fun().catch(e => console.error("nice first catch", process.version, e)) readError = null closeError = new Error("close failed") position = 0 await fun().catch(e => console.error("nice second catch", process.version, e))
- added a commit that references this issue
on Dec 25, 2025 - added a commit that references this issue
on Dec 27, 2025 - added 2 commits that reference this issue
on Jan 9, 2026 - added a commit that references this issue
on Jan 13, 2026 - added a commit that references this issue
on Jan 19, 2026 - added 4 commits that reference this issue
on Feb 17, 2026
Version
24.0.1
Platform
Subsystem
readline
What steps will reproduce the bug?
The following code creates a dummy fs that throws an error on the fs.close() call.
This error can be caught with events.once() when using the fs directly.
When using the fs together with readline, the error is not caught by events.once().
How often does it reproduce? Is there a required condition?
always
What is the expected behavior? Why is that the expected behavior?
the await once(...) also catches the error on fs.close()
What do you see instead?
Unhandled Exception error
Additional information
No response