Fixing the “NestJS Kills Itself on Unexpected Restart” Crash When Deploying to a Shared VPS – Why Chaotic PM2 Logs Hide Your Real Error and How to Uncover It in Minutes
Ever watched your NestJS app crash right after a VPS reboot, only to see a wall of noisy PM2 logs that make zero sense? You’re not alone. This article shows you exactly why those logs look like gibberish, how to expose the real stack‑trace, and a quick 5‑step fix that gets your API back up without endless guessing.
Why This Matters
If you’re running a SaaS, a micro‑service, or even a hobby project on a cheap shared VPS, uptime equals credibility (and cash). A sudden “NestJS kills itself on unexpected restart” error can shave minutes—or hours—off your SLA, frustrate users, and waste your billable hours debugging noise.
The Root Cause in One Sentence
PM2, the popular process manager, buffers crash logs and replaces the original process.exit() stack trace with its own wrapper. On a shared VPS where node_modules live on a network‑mounted drive, a missing .env or a permission glitch throws an ENOENT error that gets swallowed by PM2’s “restart” handler.
Step‑by‑Step Tutorial
-
Confirm the Crash Is From NestJS, Not PM2
Run the app manually without PM2:
node dist/main.jsIf the process exits with
Error: ENOENT: no such file or directory, open '.env', you’ve found the real culprit. -
Enable Full Stack Traces in NestJS
Add the built‑in
Loggerand setprocess.env.NODE_ENV='development'temporarily.import { Logger } from '@nestjs/common'; process.env.NODE_ENV = 'development'; Logger.error('Boot error', err.stack);This forces NestJS to print the original error before PM2 hijacks the stream.
-
Persist Critical Logs to a Separate File
Tip: Using a dedicated log file prevents PM2’s rotating buffer from overwriting your stack trace.
pm2 start dist/main.js \\ --name my‑api \\ --log-date-format='YYYY-MM-DD HH:mm:ss' \\ --output ./logs/out.log \\ --error ./logs/err.log -
Fix the .env / Permission Issue
On a shared VPS, the home directory may be mounted with
noexec. Ensure the file is readable by the user running PM2:chmod 640 .env chown youruser:yourgroup .envIf you don’t have a .env file, create a minimal one:
# .env PORT=3000 DATABASE_URL=postgres://user:pass@localhost/db -
Restart with a Clean PM2 Dump
Clear the old process list and reload:
pm2 delete all pm2 save # optional, clears dump file pm2 start ecosystem.config.js # or the command from step 3Now PM2 will show a clean “online” status and your NestJS app stays up.
Full Example: ecosystem.config.js
module.exports = {
apps: [
{
name: 'my-api',
script: 'dist/main.js',
instances: 1,
autorestart: true,
watch: false,
max_memory_restart: '300M',
env: {
NODE_ENV: 'production',
PORT: 3000,
},
error_file: './logs/err.log',
out_file: './logs/out.log',
log_date_format: 'YYYY-MM-DD HH:mm:ss',
},
],
};
Warning: Never commit your .env file to Git. Use .env.example for defaults and keep the real file out of version control.
Real‑World Use Case
John, a freelance dev, deployed a NestJS auth service on a $5/month VPS. After the provider rebooted the server, his API started returning 502 errors. The PM2 dashboard was flooded with App[my-api] exited with code 1 messages, but no clue why.
By following steps 1‑3 he discovered the missing .env caused a ENOENT. After fixing permissions and pointing PM2 to dedicated logs, the service was back up in under 10 minutes—saving him a client call and a potential $150 penalty.
Results / Outcome
- ⏱️ Reduce debugging time from hours to under 10 minutes.
- ✅ Clear, searchable error logs in
./logs/err.log. - 🔧 Avoid false “PM2 restart loops” that waste CPU on cheap VPS plans.
- 💰 Keep your SLA intact, protect revenue, and impress stakeholders.
Bonus Tips
- Use
pm2-runtimewhen containerizing with Docker to keep the same log handling. - Set
PM2_LOG_DATE_FORMATin your shell profile for consistent timestamps. - Enable
node --trace-warningsin the PM2 ecosystem to catch deprecations early. - Consider Winston for structured JSON logs that integrate with services like Papertrail.
Monetization (Optional)
If you found this guide valuable, consider buying me a coffee or hiring me for a quick VPS health audit. I’ve helped dozens of startups keep their Node.js services alive on $5‑$10 servers.
No comments:
Post a Comment