Fix ERR_USE_AFTER_CLOSE crash on Node 24+ with non-interactive stdin - #163
Conversation
inquirer 6 tears a prompt down with rl.output.end(), rl.pause(), rl.close(). When stdin is not a TTY (/dev/null, a closed pipe, CI) the readline interface receives "end" and closes itself first, so pause() runs on an already-closed interface. Node 24 made that throw ERR_USE_AFTER_CLOSE, so every authenticated command (api, deploy) dies with a stack trace and exit 1. Node 20 and 22 ignored the call. bun 1.4 behaves like Node 24. inquirer 6, 7, 8 and 9 all have the teardown bug; 10.0.0 is the first release without it. 10.x still ships a CommonJS build, so this does not repeat the ESM-only breakage of 2.4.0. IOption no longer extends inquirer's question type, which moved and narrowed between 6 and 10, and declares the fields the CLI actually uses instead. @types/inquirer is dropped because inquirer ships its own types. Verified against a live CapRover machine on Node 20.19, 22.22, 24.16, 26.2 and bun 1.4: non-interactive api calls, the interactive input/confirm path, the machine list prompt, and the masked password prompt.
processParams() handed every option to inquirer.prompt(), including the ones whose "when" resolves to false. inquirer builds a readline interface per prompt() call even when it goes on to skip the question, so the CLI was creating and tearing down an interface per skipped option on every run. That teardown is exactly where ERR_USE_AFTER_CLOSE came from before the inquirer upgrade. Resolve "when" before calling inquirer and skip the call when it is false. Behaviour is unchanged: prompt() is always called with a single option, so the answers hash passed to "when" is always empty either way.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (2)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthroughChangesInquirer migration
Estimated code review effort: 2 (Simple) | ~10 minutes Merge Risk: ⚪ Minimal · up to This PR upgrades Inquirer and avoids initializing skipped prompts, preventing the reported non-interactive stdin crash while preserving existing command parameter and validation flows. No actionable merge-blocking risk remains after normal checks and review. Suggested reviewers: Sequence Diagram(s)sequenceDiagram
participant getParams
participant whenCondition
participant inquirer
getParams->>whenCondition: resolve the when condition
whenCondition-->>getParams: return shouldAsk
alt shouldAsk is true
getParams->>inquirer: prompt the option with when=true
inquirer-->>getParams: return the prompt result
end
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Description checkExplanation The description clearly explains the issue, affected environments, implementation changes, compatibility considerations, and validation performed. It does not repeat the repository template boilerplate or confirm Slack communication, but the substantive information is complete. Full details: Docstring CoverageExplanation Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 1 files. (1 skipped: 1 unsupported.)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Fixes #162.
caprover apiandcaprover deploycrashed withERR_USE_AFTER_CLOSEon Node 24 and newer whenever stdin isnt a TTY, so CI runs and deploy scripts died with a readline stack trace and exit 1. Node 20 and 22 are fine, bun 1.4 breaks the same way. The bump toinquirer^10.2.2is what fixes it: 6, 7, 8 and 9 all have the broken teardown and 10.0.0 is the first release without it.10.xstill ships a CommonJS build so this doesnt repeat the ESM-only breakage of 2.4.0, and@types/inquirergoes away because inquirer ships its own types now.IOptionstops extending inquirer's question type, which moved and narrowed between 6 and 10, and declares the fields the CLI actually uses instead.Second commit stops
processParams()handing options toinquirer.prompt()when theirwhenis false, since inquirer builds a readline interface per call even for a question it then skips. I verified the two independiently and either one on its own fixes the reported crash, but its small and part of the same thing so I kept it as one PR. Checked on Node 20.19, 22.22, 24.16, 26.2 and bun 1.4 against a live CapRover machine: non-interactive api calls, the interactive input and confirm path, the machine list prompt, and the masked password prompt.Summary by CodeRabbit
Dependency Updates
Improvements