How to fix Error: Cannot send message on closed message port (worker disconnected) in Node.js

Node.jsINTERMEDIATEMEDIUMUpdated Dec 9, 2025ยท 203 views

This error occurs when attempting to send a message through a MessagePort that has already been closed or whose worker thread has terminated. The communication channel between the main thread and worker is no longer available.

Quick fix

Fixes Error: Cannot send message on closed message port (worker disconnected)

const { Worker } = require('worker_threads');

const worker = new Worker('./worker.js');

// Track when worker exits
worker.on('exit', (code) => {
  console.log(`Worker exited with code ${code}`);
  // Stop sending messages after this point
});

// Track when worker encounters an error
worker.on('error', (error) => {
  console.error('Worker error:', error);
});

// Track when worker is terminated
worker.on('messageerror', (error) => {
  console.error('Message error:', error);
});
  1. Track the worker lifecycle and port state
  2. Check port state before sending messages
  3. Implement graceful worker shutdown
  4. Use try-catch for defensive message sending
node.js โ€” error
const { Worker } = require('worker_threads');
const worker = new Worker('./worker.js');
// Track when worker exits
worker.on('exit', (code) => {
console.log(`Worker exited with code ${code}`);
// Stop sending messages after this point
});
// Track when worker encounters an error
worker.on('error', (error) => {
console.error('Worker error:', error);
});
// Track when worker is terminated
worker.on('messageerror', (error) => {
console.error('Message error:', error);
});
Error: Cannot send message on closed message port (worker disconnected)

What this error means

This error indicates that your code is trying to call `postMessage()` on a MessagePort that has been closed or disconnected. In Node.js worker threads, MessagePorts provide a communication channel between the main thread and worker threads. Once either side of the channel closes the port (via `close()` method) or the worker terminates, the MessagePort becomes unusable. When a worker thread exits, terminates, or explicitly closes its message port, any subsequent attempts to send messages through that port will fail with this error. The error prevents data from being sent into a void where no receiver exists to process it. This commonly happens in scenarios where the main thread continues to send messages to a worker that has already completed its task and exited, or when cleanup code closes a port but other parts of the application still hold references to it and attempt communication.

Typical symptoms

  • Error message "Cannot send message on closed message port (worker disconnected)" when calling postMessage()
  • Worker thread has exited but main thread continues sending messages
  • Application crashes when trying to communicate with terminated workers
  • Message sending succeeds initially but fails after worker completes its task
  • Port close event has fired but code still attempts to use the port

Common causes

  1. Calling postMessage() on a MessagePort after the worker thread has terminated
  2. Explicitly calling port.close() but continuing to use the port afterward
  3. Worker thread exiting while main thread still has pending messages to send
  4. Race condition where worker terminates before all messages are sent
  5. Not tracking worker lifecycle events (exit, close) properly
  6. Using a MessagePort reference after transferring it to another context
  7. Worker crashing or being terminated externally while communication is ongoing

How to fix "Error: Cannot send message on closed message port (worker disconnected)"

1Track the worker lifecycle and port state

Listen for worker exit and port close events to know when communication is no longer possible:

javascript
const { Worker } = require('worker_threads');

const worker = new Worker('./worker.js');

// Track when worker exits
worker.on('exit', (code) => {
  console.log(`Worker exited with code ${code}`);
  // Stop sending messages after this point
});

// Track when worker encounters an error
worker.on('error', (error) => {
  console.error('Worker error:', error);
});

// Track when worker is terminated
worker.on('messageerror', (error) => {
  console.error('Message error:', error);
});
2Check port state before sending messages

When using MessagePort directly, track the close event and maintain a flag:

javascript
const { MessageChannel } = require('worker_threads');

const { port1, port2 } = new MessageChannel();
let isPortOpen = true;

port1.on('close', () => {
  isPortOpen = false;
  console.log('Port closed');
});

// Safe message sending
function sendMessage(data) {
  if (isPortOpen) {
    port1.postMessage(data);
  } else {
    console.warn('Cannot send message: port is closed');
  }
}
3Implement graceful worker shutdown

Design workers to signal completion before exiting:

javascript
// main.js
const { Worker } = require('worker_threads');

const worker = new Worker('./worker.js');
let workerActive = true;

worker.on('message', (msg) => {
  if (msg.type === 'DONE') {
    workerActive = false;
    worker.terminate();
  }
});

function sendToWorker(data) {
  if (workerActive) {
    worker.postMessage(data);
  } else {
    console.log('Worker has completed, not sending message');
  }
}

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

parentPort.on('message', (data) => {
  // Process data
});

// Signal completion before exit
parentPort.postMessage({ type: 'DONE' });
4Use try-catch for defensive message sending

Wrap postMessage calls in error handling to gracefully handle closed ports:

javascript
function safeSendMessage(worker, message) {
  try {
    worker.postMessage(message);
  } catch (error) {
    if (error.message.includes('closed message port')) {
      console.warn('Worker port is closed, message not sent');
      // Handle the closed port scenario
    } else {
      throw error; // Re-throw unexpected errors
    }
  }
}
5Implement a message queue with worker pool management

For robust applications, use a worker pool that tracks active workers:

javascript
class WorkerPool {
  constructor(workerScript, poolSize) {
    this.workers = [];
    this.activeWorkers = new Set();

    for (let i = 0; i < poolSize; i++) {
      const worker = new Worker(workerScript);
      this.workers.push(worker);
      this.activeWorkers.add(worker);

      worker.on('exit', () => {
        this.activeWorkers.delete(worker);
      });
    }
  }

  sendToAvailableWorker(data) {
    const availableWorker = Array.from(this.activeWorkers)[0];

    if (availableWorker) {
      availableWorker.postMessage(data);
      return true;
    } else {
      console.warn('No active workers available');
      return false;
    }
  }

  terminate() {
    this.workers.forEach(w => w.terminate());
    this.activeWorkers.clear();
  }
}

Advanced notes

MessagePort Transfer Semantics: When you transfer a MessagePort to a worker using postMessage(data, [port]), the original port becomes unusable in the sending context. Attempting to use it will also cause this error. Always track which context owns the port after transfer.

Event Loop Timing: Messages sent via postMessage() are asynchronous. If a worker exits immediately after processing, there's a race condition where the main thread might try to send a message after the worker has already terminated but before the exit event has been processed. Use explicit coordination (acknowledgment messages) for critical scenarios.

Memory Leaks: Failing to clean up worker references when they exit can cause memory leaks. Always remove event listeners and clear references when workers terminate.

Cluster vs Worker Threads: This error is specific to worker_threads MessagePort. If using the cluster module, you'll encounter different IPC (Inter-Process Communication) errors. The cluster module uses a different communication mechanism.

Debugging: Enable NODE_DEBUG=worker environment variable to see detailed worker thread lifecycle events that can help identify when and why ports are closing unexpectedly.

Frequently asked questions

What does "Error: Cannot send message on closed message port (worker disconnected" mean?
This error indicates that your code is trying to call postMessage() on a MessagePort that has been closed or disconnected. js worker threads, MessagePorts provide a communication channel between the main thread and worker threads. Once either side of the channel closes the port (via close() method) or the worker terminates, the MessagePort becomes unusable.
How do I fix "Error: Cannot send message on closed message port (worker disconnected"?
This error occurs when attempting to send a message through a MessagePort that has already been closed or whose worker thread has terminated. The communication channel between the main thread and worker is no longer available.
What causes "Error: Cannot send message on closed message port (worker disconnected"?
Calling postMessage() on a MessagePort after the worker thread has terminated Explicitly calling port.close() but continuing to use the port afterward Worker thread exiting while main thread still has pending messages to send
Is the "Error: Cannot send message on closed message port (worker disconnected" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading