How to fix Error: Uncaught exception in main process (unhandled error) in Node.js

Node.jsINTERMEDIATECRITICALUpdated Dec 9, 2025ยท 197 views

An uncaught exception occurs when a JavaScript error is thrown but not caught by any try-catch block or error handler, causing the application to crash. This indicates the application is in an undefined state and must be properly handled to prevent data corruption.

Quick fix

Fixes Error: Uncaught exception in main process (unhandled error)

process.on('uncaughtException', (error) => {
  console.error('Uncaught Exception:', error);
  console.error('Stack trace:', error.stack);

  // Perform cleanup if necessary
  // Close database connections, file handles, etc.

  // Exit the process - DO NOT continue running
  process.exit(1);
});
  1. Add an uncaughtException handler for logging
  2. Identify the source of the uncaught exception
  3. Wrap error-prone code in try-catch blocks
  4. Add error listeners to EventEmitters
node.js โ€” error
process.on('uncaughtException', (error) => {
console.error('Uncaught Exception:', error);
console.error('Stack trace:', error.stack);
// Perform cleanup if necessary
// Close database connections, file handles, etc.
// Exit the process - DO NOT continue running
process.exit(1);
});
Error: Uncaught exception in main process (unhandled error)

What this error means

An uncaught exception in Node.js happens when an error is thrown synchronously but isn't caught by any try-catch block, eventually bubbling up to the event loop. When Node.js encounters an uncaught exception, it prints the stack trace to stderr and terminates the process with exit code 1 by default. This is Node.js's safety mechanism - when an error reaches this point, it means your application is in an undefined state. The runtime doesn't know what variables might be corrupted, what connections might be left open, or what operations were interrupted mid-execution. Continuing to run in this state could lead to data corruption, memory leaks, or unpredictable behavior. While you can listen for the 'uncaughtException' event on the process object to log errors before shutdown, the Node.js documentation strongly advises against attempting to resume normal operation after catching such exceptions. The proper approach is to log the error for debugging and allow the process to exit cleanly.

Typical symptoms

  • Application crashes immediately after an error is thrown
  • Process exits with code 1
  • Stack trace printed to stderr showing where the error originated
  • No custom error handling catches the exception
  • Error message appears in logs with full call stack
  • Application stops responding to requests mid-operation

Common causes

  1. Missing try-catch blocks around synchronous code that can throw errors
  2. Throwing errors in callback functions without proper error handling
  3. Event emitters throwing 'error' events with no registered error listeners
  4. Syntax errors or runtime errors in required modules during initialization
  5. Third-party library throwing unexpected errors not documented in their API
  6. Type errors from accessing properties on null or undefined values
  7. Reference errors from accessing undeclared variables
  8. Asynchronous code using callbacks that throw instead of returning errors

How to fix "Error: Uncaught exception in main process (unhandled error)"

1Add an uncaughtException handler for logging

Before fixing the root cause, add a global handler to log uncaught exceptions. This helps identify where errors are occurring:

javascript
process.on('uncaughtException', (error) => {
  console.error('Uncaught Exception:', error);
  console.error('Stack trace:', error.stack);

  // Perform cleanup if necessary
  // Close database connections, file handles, etc.

  // Exit the process - DO NOT continue running
  process.exit(1);
});

Important: This should only log and exit. Never try to resume normal operation after an uncaught exception.

2Identify the source of the uncaught exception

Review the stack trace to find where the error originated. Look for:

bash
# Example stack trace
Error: Cannot read property 'id' of undefined
    at processUser (/app/user-handler.js:45:23)
    at handleRequest (/app/routes.js:112:5)
    at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5)

The top frame (processUser) shows where the error was thrown. Examine the code at that location to understand what went wrong.

3Wrap error-prone code in try-catch blocks

For synchronous code that can throw errors, use try-catch blocks:

javascript
// Before: crashes on error
function processData(input) {
  const parsed = JSON.parse(input); // Can throw SyntaxError
  return parsed.data.value; // Can throw TypeError if data is undefined
}

// After: proper error handling
function processData(input) {
  try {
    const parsed = JSON.parse(input);
    if (!parsed || !parsed.data) {
      throw new Error('Invalid data structure');
    }
    return parsed.data.value;
  } catch (error) {
    console.error('Failed to process data:', error);
    throw new Error(`Data processing failed: ${error.message}`);
  }
}
4Add error listeners to EventEmitters

EventEmitter objects that emit 'error' events without listeners will cause uncaught exceptions:

javascript
const { EventEmitter } = require('events');

const emitter = new EventEmitter();

// Before: crashes if error is emitted
// emitter.emit('error', new Error('Something broke'));

// After: proper error handling
emitter.on('error', (error) => {
  console.error('Emitter error:', error);
  // Handle or re-throw as appropriate
});

// Now safe to emit errors
emitter.emit('error', new Error('Something broke'));

This is especially important for streams, HTTP servers, and database connections.

5Use proper callback error handling

In callback-style async code, always check for errors and never throw inside callbacks:

javascript
const fs = require('fs');

// Bad: throwing in callback causes uncaught exception
fs.readFile('/path/to/file', (err, data) => {
  if (err) throw err; // DON'T DO THIS
  console.log(data);
});

// Good: pass errors to callback or handle them
fs.readFile('/path/to/file', (err, data) => {
  if (err) {
    console.error('File read error:', err);
    return; // or pass to next callback in chain
  }
  console.log(data);
});
6Set up a process manager for automatic restarts

Use a process manager like PM2 to automatically restart your application when it crashes:

bash
# Install PM2
npm install -g pm2

# Start your application
pm2 start app.js --name my-app

# Configure max restarts and restart delay
pm2 start app.js --max-restarts 10 --restart-delay 3000

# View logs
pm2 logs my-app

Or use Docker with a restart policy:

yaml
# docker-compose.yml
services:
  app:
    image: node:20
    restart: unless-stopped
    command: node app.js

This ensures your application recovers from crashes while you fix the underlying issues.

Advanced notes

Understanding the Risk of Continuing After Uncaught Exceptions

When an uncaught exception occurs, the application state becomes undefined. Variables may hold partial data, database transactions may be incomplete, file handles may be left open, and memory structures may be corrupted. The Node.js documentation explicitly warns against attempting to resume operation because:

1. Memory leaks: Event listeners and timers may not be properly cleaned up
2. Resource exhaustion: Open connections and file handles accumulate over time
3. Data corruption: Writes may be partially complete or in inconsistent states
4. Cascading failures: The corrupted state causes additional errors downstream

Unhandled Promise Rejections

Similar to uncaught exceptions, unhandled promise rejections occur when promises are rejected without a .catch() handler. As of Node.js 15+, these also terminate the process by default. Handle them separately:

javascript
process.on('unhandledRejection', (reason, promise) => {
  console.error('Unhandled Rejection at:', promise);
  console.error('Reason:', reason);
  process.exit(1);
});

Centralized Error Handling

For Express applications, implement error-handling middleware as the last middleware in your chain:

javascript
app.use((err, req, res, next) => {
  console.error('Express error:', err);
  res.status(500).json({ error: 'Internal server error' });
});

This catches errors from route handlers and middleware, preventing them from becoming uncaught exceptions.

Monitoring and Alerting

Integrate error monitoring services like Sentry, Datadog, or New Relic to track uncaught exceptions in production. These services provide:
- Real-time alerts when crashes occur
- Stack traces with source maps
- Context about the error (request data, user info, environment)
- Historical trends to identify patterns

Graceful Shutdown

When an uncaught exception occurs, perform cleanup before exiting:

javascript
process.on('uncaughtException', async (error) => {
  console.error('Uncaught Exception:', error);

  try {
    // Close database connections
    await db.close();

    // Stop accepting new connections
    server.close();

    // Flush logs
    await logger.flush();
  } catch (cleanupError) {
    console.error('Cleanup error:', cleanupError);
  }

  process.exit(1);
});

Set a timeout to force exit if cleanup takes too long:

javascript
const SHUTDOWN_TIMEOUT = 10000; // 10 seconds

process.on('uncaughtException', async (error) => {
  console.error('Uncaught Exception:', error);

  const forceExit = setTimeout(() => {
    console.error('Forced shutdown after timeout');
    process.exit(1);
  }, SHUTDOWN_TIMEOUT);

  forceExit.unref(); // Allow process to exit naturally if cleanup finishes

  // Perform cleanup...
});

Frequently asked questions

What does "Error: Uncaught exception in main process (unhandled error)" mean?
js happens when an error is thrown synchronously but isn't caught by any try-catch block, eventually bubbling up to the event loop. js encounters an uncaught exception, it prints the stack trace to stderr and terminates the process with exit code 1 by default. js's safety mechanism - when an error reaches this point, it means your application is in an undefined state.
How do I fix "Error: Uncaught exception in main process (unhandled error)"?
An uncaught exception occurs when a JavaScript error is thrown but not caught by any try-catch block or error handler, causing the application to crash. This indicates the application is in an undefined state and must be properly handled to prevent data corruption.
What causes "Error: Uncaught exception in main process (unhandled error)"?
Missing try-catch blocks around synchronous code that can throw errors Throwing errors in callback functions without proper error handling Event emitters throwing 'error' events with no registered error listeners
Is the "Error: Uncaught exception in main process (unhandled error)" error serious?
Yes. This is a critical-severity error that usually blocks work until it is fixed, but the steps above resolve it.

Official resources & further reading