How to fix npm ERR! code SIGTERM npm ERR! errno SIGTERM npm ERR! process terminated with SIGTERM in npm
The npm SIGTERM error occurs when npm receives a termination signal, typically from container orchestrators, process managers, or system shutdowns, and fails to pass it gracefully to the Node.js child process.
Quick fix
Fixes npm ERR! code SIGTERM npm ERR! errno SIGTERM npm ERR! process terminated with SIGTERM
# ❌ Before (bad - npm intercepts signals)
CMD npm start
# ✅ After (good - Node.js is PID 1)
CMD ["node", "./dist/index.js"]- Run Node.js directly instead of through npm
- Use exec form in Dockerfile
- Add SIGTERM signal handler to your application
- Use Docker --init flag or Tini for signal forwarding
# ❌ Before (bad - npm intercepts signals)CMD npm start# ✅ After (good - Node.js is PID 1)CMD ["node", "./dist/index.js"]npm ERR! code SIGTERMnpm ERR! errno SIGTERMnpm ERR! process terminated with SIGTERM
What this error means
SIGTERM (signal termination) is a Unix signal that tells a process to terminate gracefully. When npm receives a SIGTERM signal—typically from a container orchestrator, process manager, or deployment platform—it should pass that signal to its child Node.js process. However, npm doesn't reliably forward this signal, causing npm to immediately kill the Node.js process instead of allowing graceful shutdown. The root cause is architectural: when you run npm run <script>, npm becomes the main process, and your Node.js application becomes a child process. Unlike proper process managers, npm doesn't intercept signals intelligently. When Linux sends SIGTERM to the npm process group, npm kills all children without forwarding the signal, preventing your application from running cleanup routines. This issue is particularly prevalent in Docker containers, Kubernetes, Heroku, and CI/CD platforms where signal routing is critical for graceful shutdowns.
Typical symptoms
- Application terminates immediately when container receives docker stop or orchestrator sends shutdown signal
- npm ERR! code SIGTERM and npm ERR! errno SIGTERM appear in logs
- Graceful shutdown handlers (process.on('SIGTERM')) never execute; cleanup code doesn't run
- Database connections hang open; pending requests get orphaned; resources leak
- Local development works fine with Ctrl+C, but production deployments fail on orchestrated shutdowns
- Exit code 143 (128 + 15) appears in deployment logs
Common causes
- Running Node.js through npm instead of directly—npm becomes PID 1 and doesn't forward SIGTERM
- Using shell form in Dockerfile (CMD npm start) which breaks signal chain
- Process not running as PID 1 in Docker, so it doesn't receive the container's SIGTERM
- Memory limits exceeded in cloud environments causing platform to kill the process
- npm version incompatibility (versions 9.6.7 to 9.8.1 have known signal handling bugs)
- Missing SIGTERM handlers in application code
How to fix "npm ERR! code SIGTERM npm ERR! errno SIGTERM npm ERR! process terminated with SIGTERM"
The simplest and most effective fix is to run Node.js directly instead of through npm:
In your Dockerfile, change:
# ❌ Before (bad - npm intercepts signals)
CMD npm start
# ✅ After (good - Node.js is PID 1)
CMD ["node", "./dist/index.js"]For Heroku or cloud platforms, update your Procfile:
# ❌ Before
web: npm start
# ✅ After
web: node ./dist/index.jsThis ensures your Node.js process becomes PID 1 and receives signals directly.
Ensure you're using the exec form (JSON array format) instead of shell form:
# ❌ Shell form (bad - signals lost in shell)
CMD "node ./src/index.js"
# ✅ Exec form (good - signals forwarded directly)
CMD ["node", "./src/index.js"]The exec form tells Docker to execute the command directly without wrapping it in /bin/sh -c, preserving signal routing.
Add signal handlers at the top of your main application file:
// index.js - add at the very top
process.on('SIGTERM', () => {
console.log('SIGTERM received, starting graceful shutdown...');
server.close(() => {
console.log('HTTP server closed');
process.exit(0);
});
});
process.on('SIGINT', () => {
console.log('SIGINT received, shutting down...');
process.exit(0);
});
const express = require('express');
const app = express();
const server = app.listen(3000, () => {
console.log('Server running on port 3000');
});Register handlers before calling listen() so they're available when shutdown signals arrive.
Use an init system to ensure signals are properly forwarded:
Option A: Use Docker --init flag:
docker run --init -p 3000:3000 my-node-appOption B: Use Tini in your Dockerfile:
FROM node:20-alpine
RUN apk add --no-cache tini
WORKDIR /app
COPY . .
RUN npm ci --omit=dev
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["node", "./dist/index.js"]Option C: In docker-compose.yml:
services:
app:
build: .
init: true
ports:
- "3000:3000"In some cloud platforms, SIGTERM is sent when your application exceeds its memory limit:
# Locally, test with memory constraints:
node --max-old-space-size=256 ./dist/index.jsOptimize memory usage:
// ✅ Use streaming instead of loading entire datasets
app.get('/data', (req, res) => {
fs.createReadStream('large-file.json').pipe(res);
});
// ❌ Avoid: loading entire file into memory
app.get('/data', (req, res) => {
const data = fs.readFileSync('large-file.json');
res.send(data);
});If your platform consistently sends SIGTERM shortly after startup, increase your memory allocation.
Advanced notes
Process Management Context: SIGTERM is part of the Unix process management protocol. When you send docker stop, Kubernetes performs a graceful shutdown, or a process manager needs to terminate an application, it sends SIGTERM (signal 15) first, giving the process ~10 seconds to shut down gracefully. If the process doesn't exit, it sends SIGKILL (signal 9), which cannot be caught.
PID 1 and Signal Handling: In Unix/Linux, PID 1 is the init process with special signal handling rules. Node.js doesn't naturally handle being PID 1 well, which is why it won't respond to SIGINT or SIGTERM when it's the container's main process. This is solved by using an init system (Tini, dumb-init) or not making npm/Node PID 1.
Kubernetes-Specific: Kubernetes sends SIGTERM with a default grace period of 30 seconds. Ensure your signal handler exits within this window. Also check readiness and liveness probes—a failed readiness probe doesn't stop the pod; only deleting it or a SIGTERM will.
Frequently asked questions
- What does "npm ERR! code SIGTERM npm ERR! errno SIGTERM npm ERR! process terminat" mean?
- SIGTERM (signal termination) is a Unix signal that tells a process to terminate gracefully. js process. js process instead of allowing graceful shutdown.
- How do I fix "npm ERR! code SIGTERM npm ERR! errno SIGTERM npm ERR! process terminat"?
- The npm SIGTERM error occurs when npm receives a termination signal, typically from container orchestrators, process managers, or system shutdowns, and fails to pass it gracefully to the Node.js child process.
- What causes "npm ERR! code SIGTERM npm ERR! errno SIGTERM npm ERR! process terminat"?
- Running Node.js through npm instead of directly—npm becomes PID 1 and doesn't forward SIGTERM Using shell form in Dockerfile (CMD npm start) which breaks signal chain Process not running as PID 1 in Docker, so it doesn't receive the container's SIGTERM
- Is the "npm ERR! code SIGTERM npm ERR! errno SIGTERM npm ERR! process terminat" error serious?
- It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- 📚npm Official Documentation
- 📖Docs: Node.js child processes(Official Docs)
- 🐙GitHub: npm issues(GitHub)
- 💬SO: SIGTERM signal handling(Stack Overflow)