Course contentsShow
← Node.js
Lesson 1432 of 1,98013. Error Handling and Resilient SystemsFree lesson

Handling Unexpected Rejections in Workers

You will coordinate error handling across Worker Threads to ensure a failure in a computation doesn't take down the main thread.

In this lesson, you will learn how to capture unhandled promise rejections inside Node.js Worker Threads to prevent a single failing task from crashing your entire application.

When working with worker_threads, a common pitfall is assuming that an error inside a worker will bubble up gracefully to the main thread. By default, an unhandled promise rejection or an uncaught exception inside a worker will trigger the 'error' event on the Worker instance in your main thread, which can terminate the worker abruptly and potentially leak resources or leave your application in an inconsistent state.

Containing the Blast Radius

To manage these unexpected failures, you must treat the worker as an isolated system. The goal is to catch rejections within the worker before they reach the Node.js process level. You can achieve this by attaching an event listener to the process object inside the worker script:

// worker.js
const { parentPort } = require('worker_threads');

process.on('unhandledRejection', (reason, promise) => {
  // Log the error for observability
  console.error('Unhandled Rejection in Worker:', reason);
  
  // Inform the main thread before dying or resetting
  parentPort.postMessage({ type: 'error', error: reason.message });
  
  // Graceful cleanup if necessary
  process.exit(1); 
});

// Your logic here...
async function performTask() {
  throw new Error('Critical calculation failure!');
}
performTask();

By intercepting the rejection, you gain control over the failure lifecycle. Instead of the worker simply vanishing or crashing silently, you can send a structured message back to the main thread via parentPort.

On the main thread side, ensure you listen for these custom error messages alongside the native worker.on('error') event. This two-layered approach—catching errors inside the worker and listening for them in the main thread—ensures your orchestrator can decide whether to restart the worker, log the failure to a monitoring service, or mark the specific task as failed without bringing down the main event loop.

Key Takeaway: Never rely on default process-level crash behavior; always intercept unhandledRejection within your worker threads to report failure metadata back to the orchestrator before terminating.