Skip to content

noctcore-code-quality/no-process-exit

process.exit() belongs to bootstrap/shutdown and CLIs — not application code.

Recommended preset: error · Autofix: no · Suggestions: no · Type information: not needed

process.exit() kills the whole process immediately, skipping pending I/O, finally blocks, and graceful-shutdown handlers. In request-scoped, service, or renderer code that is a footgun: a single call can take the entire process down mid-flight. Those layers should throw or reject and let the lifecycle decide how to tear down. The legitimate exit sites are standalone scripts, CLI entrypoints, and config files.

Any process.exit(...) call in a file not covered by allowIn. Both the dot form (process.exit()) and the computed form (process['exit']()) are caught so a computed callee cannot bypass the rule.

Incorrect · src/orders/orders.service.ts
if (!order) {
process.exit(1);
}
Correct · src/orders/orders.service.ts
if (!order) {
throw new Error('order not found');
}

Moving the exit to a CLI entrypoint is the other fix:

Correct · scripts/migrate.ts
main().catch(() => process.exit(1));
  • Files covered by allowIn: by default scripts, bin and cli directories, and config files.
  • An exit method on anything other than process (queue.exit(0)).
  • Setting process.exitCode, which lets the process finish its work before it ends.
Option Type Default Meaning
allowIn string[] (globs) see below File-path globs where process.exit() is allowed.

The globs are matched against the file path (a leading **/ may match zero leading directories, so the same pattern works for absolute and project-relative paths). Default:

["**/scripts/**", "**/bin/**", "**/cli/**", "**/*.config.{ts,js,mjs,cjs,cts,mts}"]
'noctcore-code-quality/no-process-exit': ['error', { allowIn: ['**/scripts/**', '**/*.cli.ts'] }]

Standalone CLI projects where every file is legitimately an entrypoint.