Skip to content

Add an option not to trap SIGINT (Ctrl + C) to readline.creatInterface #61487

Description

@tats-u

What is the problem this feature will solve?

Here is a typical code to accepts multiple lines from stdin:

import { stdin, stderr } from "node:process";
import { createInterface } from "node:readline/promises";

const rl = createInterface({ input: stdin, output: stderr });

for await (const line of rl) {
  // process line
}
console.log("Done");

However, if you press Ctrl + C, it is treated as Ctrl + D—i.e. "Done" is displayed and you cannot cancel the multiline input. It is a ridiculous behavior.

await rl.question() throws AbortError and messes up your terminal:

$ node ./test.mjs
node:internal/readline/interface:1331
            this[kQuestionReject]?.(new AbortError('Aborted with Ctrl+C'));
                                    ^

AbortError: Aborted with Ctrl+C
    at [_ttyWrite] (node:internal/readline/interface:1331:37)
    at ReadStream.onkeypress (node:internal/readline/interface:284:20)
    at ReadStream.emit (node:events:508:28)
    at emitKeys (node:internal/readline/utils:371:14)
    at emitKeys.next (<anonymous>)
    at ReadStream.onData (node:internal/readline/emitKeypressEvents:64:36)
    at ReadStream.emit (node:events:508:28)
    at addChunk (node:internal/streams/readable:559:12)
    at readableAddChunkPushByteMode (node:internal/streams/readable:510:3)
    at Readable.push (node:internal/streams/readable:390:5) {
  code: 'ABORT_ERR'
}

It is not sophisticated.

What is the feature you are proposing to solve the problem?

Add an option to creatInterface to prevent it from trapping SIGINT by default.

const rl = createInterface({ input: stdin, output: stderr, noTrapSigInt: true });

With this, you will be able to press Ctrl + C to terminate the program immediately with the proper exit code.

What alternatives have you considered?

import { platform } from "node:process";

rl.on("SIGINT", () => {
  process.exit(platform === "win32" ? -1073741510 : 130);
});

Why do I have to add such a code? Who the hell can remember such numbers for both platforms?

Activity

  1. aduh95 commented on Jan 23, 2026

    @aduh95
    Contributor

    Wouldn't a try/catch cover your use-case?

    import { stdin, stderr } from "node:process";
    import { createInterface } from "node:readline/promises";
    
    const rl = createInterface({ input: stdin, output: stderr });
    
    try {
      await rl.question('question? ');
    } catch {}
    
    console.log("Done");
  2. tats-u commented on Jan 23, 2026

    @tats-u
    Author

    catch {} is the worst. "Done" must never displayed by Ctrl + C. The app must be immediately interrupted with a proper exit code.

  3. aduh95 commented on Jan 23, 2026

    @aduh95
    Contributor

    catch { process.exit(1); } then, you catch my drift

  4. tats-u commented on Jan 24, 2026

    @tats-u
    Author

    You don't know much about what appropriate return code is. You must tell "exited by Ctrl + C" from "abnormally terminated by error" (status code 1).

    void main() {
        IO.println("input: " + IO.readln());
    }

    This Java returns 130. This is the standard return code by Ctrl + C in non-Windows, but Java in Windows also returns this code.

    import { stdin } from "node:process"
    
    for await (const line of stdin) {
        console.log(line);
    }

    This returns -1073741510 (0xC000013A) when you press Ctrl + C in Windows. Who can remember such a complex number?

    I won't let you just give this a quick fix to keep up appearances.

  5. aduh95 commented on Jan 24, 2026

    @aduh95
    Contributor

    I won't let you just give this a quick fix to keep up appearances.

    Maybe instead of assuming ill-intent on my side (why would I f-ing care about appearances? Do you really believe that your issue among the 1.7k open ones has any impact on anyone's reputation?), you could take my comments as me simply trying to help you. I didn't mean to sound dismissive, the code snippet I shared was not listed in the What alternatives have you considered? section, so I thought maybe you hadn't considered it.
    I really don't like your tone, and you don't seem to like my help, so I'm just going to disengage from this conversation.

  6. tats-u commented on Jan 24, 2026

    @tats-u
    Author

    you could take my comments as me simply trying to help you. I didn't mean to sound dismissive

    Regrettably, your response didn't convey that intent. Instead, it appeared dismissive, suggesting that a simple workaround should suffice for a problem you seem to consider insignificant. While it's unfortunate there was a misunderstanding, I question whether you thoroughly reviewed the section regarding "What alternatives have you considered?" before responding.

    I shared was not listed in the What alternatives have you considered?

    Your workaround is functionally the same as mine. Didn't the exception message and my listed alternatives make it clear enough that I was already aware of that?

  7. aduh95 commented on Jan 24, 2026

    @aduh95
    Contributor

    If when you receive a dismissive comment, and you conclude "surely this person is trying cover up for appearances" instead of "clearly I did not do a good enough job at explaining the issue", well you're just setting yourself up for having a very unproductive conversation.
    btw if you're not interested in workarounds, just send a PR, it'd be a better use of everyone's time.

  8. tats-u commented on Jan 24, 2026

    @tats-u
    Author

    I assumed you'd figure it out, so I cut corners on the explanation, but that was a mistake.

    just send a PR, it'd be a better use of everyone's time.

    Who would send a PR right off the bat without discussing or getting approval of its design? This is not a bug fix, so at least its property name must be determined. My suggested name is not so good.

  9. crydafan commented on Jan 24, 2026

    @crydafan

    I saw this last night but I didn't do any PRs because this issue was sent to 'Awaiting Triage', I'd really like to send a PR with a new feature that addresses this issue.
    Edit: Just saw that #61489 has a PR attached to it, I'll do my very best to implement this feature.

  10. github-actions commented on Jul 20, 2026

    @github-actions
    Contributor

    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.

  11. added
    staleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.
    on Jul 20, 2026
  12. tats-u commented on Jul 20, 2026

    @tats-u
    Author

    Not stale

  13. removed
    staleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.
    on Jul 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature requestIssues requesting new Node.js features.

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions