SIGINT errors occur when an npm script is interrupted, typically by Ctrl+C. This is usually normal behavior, not an actual error—npm reports non-zero exits from interrupted processes.
Fixes npm ERR! code ELIFECYCLE npm ERR! errno SIGINT npm ERR! process terminated with signal SIGINT
# Running dev server
npm run dev
# ... server running ...
# Press Ctrl+C
^C
npm ERR! code ELIFECYCLE
npm ERR! errno SIGINT# Running dev servernpm run dev# ... server running ...# Press Ctrl+C^Cnpm ERR! code ELIFECYCLEnpm ERR! errno SIGINTnpm ERR! code ELIFECYCLEnpm ERR! errno SIGINTnpm ERR! process terminated with signal SIGINT
SIGINT (signal 2) is the interrupt signal, typically sent when you press Ctrl+C in the terminal. When npm reports this as an error, it's because the child process exited with a non-zero status code (130 = 128 + 2). In most cases, this is expected behavior—you intentionally stopped the process. npm reports it as an error because any non-zero exit code is technically a failure. The "error" message can be safely ignored when you deliberately interrupted the process.
If you pressed Ctrl+C, this "error" is expected:
# Running dev server
npm run dev
# ... server running ...
# Press Ctrl+C
^C
npm ERR! code ELIFECYCLE
npm ERR! errno SIGINTThe process stopped as requested. The error message is just npm reporting the non-zero exit code.
If you need cleanup on Ctrl+C:
process.on('SIGINT', async () => {
console.log('\nReceived SIGINT. Cleaning up...');
// Close connections, save state, etc.
await cleanup();
// Exit cleanly
process.exit(0);
});Use process.once('SIGINT', ...) to avoid double handling.
npm has known issues forwarding signals:
# Instead of
npm run dev
# Run directly
node --watch src/index.js
# or
npx tsx watch src/index.tsDirect execution gives you cleaner signal handling.
If the error message bothers you, handle it in the script:
{
"scripts": {
"dev": "node server.js || true"
}
}The || true prevents the non-zero exit from showing as error. Use carefully—it hides real errors too.
If you need to press Ctrl+C twice:
// Force exit on second SIGINT
let isShuttingDown = false;
process.on('SIGINT', () => {
if (isShuttingDown) {
console.log('Force exit');
process.exit(1);
}
isShuttingDown = true;
console.log('Shutting down gracefully... (Ctrl+C again to force)');
// Graceful shutdown
server.close(() => process.exit(0));
});For cancelled CI jobs, handle gracefully:
GitHub Actions:
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 10 # Set reasonable timeout
steps:
- run: npm test
continue-on-error: true # Don't fail on interruptCheck if the job was cancelled vs actually failed in your script logic.
The SIGINT "error" is a cosmetic issue in npm. The npm team has discussed this but hasn't changed the behavior because technically any non-zero exit is a failure.
On Windows, signal handling works differently. Ctrl+C sends a different event, and SIGINT may not behave the same as on Unix systems. Use Ctrl+Break for harder interrupts on Windows.
For development servers like Next.js, Vite, or webpack-dev-server, this error on Ctrl+C is completely normal and expected. These tools handle their own cleanup before exiting.