This error occurs when attempting to call cluster.fork() from a worker process instead of the primary (master) process. The cluster module enforces a strict master-worker hierarchy where only the primary process can spawn new workers.
This error indicates a fundamental violation of the Node.js cluster module's architecture. The cluster module is designed with a master-worker pattern where a single primary process manages multiple worker processes. The cluster.fork() method is exclusively available to the primary process and is used to spawn new worker processes. When you see this error, it means code is attempting to call cluster.fork() from within a worker process (a child process that was already forked). This is not allowed because worker processes are meant to handle application logic, not spawn additional workers. The cluster.fork() method is not exported in worker processes, so any attempt to use it will fail. This restriction exists to maintain a clear hierarchy and prevent confusion about which process is responsible for worker management. Only the primary process should orchestrate the worker pool, while workers focus on processing requests or tasks.
Check your cluster setup code and ensure cluster.fork() is only called within a primary process check:
const cluster = require('cluster');
const os = require('os');
// CORRECT: Fork only in primary process
if (cluster.isPrimary) {
console.log(`Primary process ${process.pid} is running`);
// Fork workers equal to CPU cores
const numCPUs = os.cpus().length;
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log(`Worker ${worker.process.pid} died`);
});
} else {
// Worker process - NO cluster.fork() here
console.log(`Worker ${process.pid} started`);
// Your application logic goes here
}Ensure all cluster.fork() calls are inside the if (cluster.isPrimary) block.
If using older code with cluster.isMaster, update to the modern cluster.isPrimary API:
// Old (deprecated but still works)
if (cluster.isMaster) {
cluster.fork();
}
// New (recommended)
if (cluster.isPrimary) {
cluster.fork();
}Note: cluster.isMaster still works but is deprecated in favor of cluster.isPrimary. Use isPrimary in new code.
Ensure your application logic is clearly separated between primary and worker processes:
const cluster = require('cluster');
const express = require('express');
const os = require('os');
if (cluster.isPrimary) {
// PRIMARY PROCESS CODE ONLY
console.log(`Primary ${process.pid} is running`);
// Fork workers
for (let i = 0; i < os.cpus().length; i++) {
cluster.fork();
}
// Handle worker events
cluster.on('exit', (worker, code, signal) => {
console.log(`Worker ${worker.process.pid} died, spawning new worker`);
cluster.fork(); // OK to fork here - still in primary
});
} else {
// WORKER PROCESS CODE ONLY
// NO cluster.fork() calls allowed here
const app = express();
app.get('/', (req, res) => {
res.send(`Worker ${process.pid} handled request`);
});
app.listen(3000, () => {
console.log(`Worker ${process.pid} listening on port 3000`);
});
}Never mix worker application logic with cluster management code.
If you have shared modules loaded by both primary and worker processes, ensure they do not contain cluster.fork() calls:
// shared-module.js - WRONG
const cluster = require('cluster');
function init() {
cluster.fork(); // ERROR: Will fail if called from worker
}
// shared-module.js - CORRECT
const cluster = require('cluster');
function init() {
if (cluster.isPrimary) {
cluster.fork(); // Only forks if called from primary
}
}Review all modules that use the cluster module to ensure proper process checks.
Node.js uses the NODE_WORKER_ID environment variable to distinguish workers from the primary process. Verify this is not being manipulated:
const cluster = require('cluster');
console.log('Is Primary:', cluster.isPrimary);
console.log('Is Worker:', cluster.isWorker);
console.log('Worker ID:', cluster.worker?.id || 'N/A');
console.log('NODE_WORKER_ID:', process.env.NODE_WORKER_ID);
// cluster.isPrimary is true when NODE_WORKER_ID is undefined
// cluster.isWorker is true when NODE_WORKER_ID is definedDo not manually set or modify the NODE_WORKER_ID environment variable.
Master vs Primary Terminology: Node.js renamed cluster.isMaster to cluster.isPrimary in version 16+ to use more inclusive language. Both properties exist for backward compatibility, but new code should use isPrimary.
Dynamic Worker Spawning: If you need to spawn workers dynamically based on load, implement this logic in the primary process only. Use IPC messages from workers to signal the primary process to spawn additional workers, rather than having workers fork directly.
Worker Pool Management: While Node.js provides the cluster.fork() method, it does not automatically manage worker pool sizing. You are responsible for monitoring worker health, respawning crashed workers, and adjusting the pool size based on your application's needs. Consider using process managers like PM2 for production deployments.
Alternative Patterns: For some use cases, Node.js worker threads (worker_threads module) may be more appropriate than clustering. Worker threads share memory and are lighter weight than separate processes, but clustering provides better isolation and is more suitable for scaling web servers across CPU cores.
Load Balancing: The cluster module handles load balancing automatically. On most platforms, it uses a round-robin approach where the primary process distributes incoming connections to workers. On Windows, connections are handled directly by workers with the operating system balancing the load.
Error: Listener already called (once event already fired)
EventEmitter listener already called with once()
Error: EACCES: permission denied, open '/root/file.txt'
EACCES: permission denied
Error: Invalid encoding specified (stream encoding not supported)
How to fix Invalid encoding error in Node.js readable streams
Error: EINVAL: invalid argument, open
EINVAL: invalid argument, open
TypeError: readableLength must be a positive integer (stream config)
TypeError: readableLength must be a positive integer in Node.js streams