discordjs/discord.js · error · Error
Expected WorkerBootstrap to not be used within the main thre
Error message
Expected WorkerBootstrap to not be used within the main thread
What it means
WorkerBootstrapper is the utility that boots shard management code inside a worker_threads worker; its constructor mirrors the strategy guard and throws if isMainThread is true. A main-thread worker bootstrapper makes no sense since it relies on parentPort to receive shard spawn instructions from the main thread. Use WebSocketManager directly on the main thread instead.
Source
Thrown at packages/ws/src/utils/WorkerBootstrapper.ts:47
}
/**
* Utility class for bootstrapping a worker thread to be used for sharding
*/
export class WorkerBootstrapper {
/**
* The data passed to the worker thread
*/
protected readonly data = workerData as WorkerData;
/**
* The shards that are managed by this worker
*/
protected readonly shards = new Collection<number, WebSocketShard>();
public constructor() {
if (isMainThread) {
throw new Error('Expected WorkerBootstrap to not be used within the main thread');
}
}
/**
* Helper method to initiate a shard's connection process
*/
protected async connect(shardId: number): Promise<void> {
const shard = this.shards.get(shardId);
if (!shard) {
throw new RangeError(`Shard ${shardId} does not exist`);
}
await shard.connect();
}
/**
* Helper method to destroy a shard
*/View on GitHub (pinned to a81ed8a306)
Solutions
- Only instantiate WorkerBootstrapper inside the script referenced as the worker path (executed by worker_threads), wrapped in an if (!isMainThread) branch.
- On the main thread, construct WebSocketManager with WorkerShardingStrategy and pass options; let it spawn the workers that run the bootstrapper.
- If the entry file is both main and worker, guard with isMainThread and run WorkerBootstrapper only in the worker branch.
Example fix
// before (entry.js, runs as both main and worker)
new WorkerBootstrapper().start();
// after
import { isMainThread } from 'node:worker_threads';
if (isMainThread) {
const manager = new WebSocketManager({ ... });
await manager.spawn();
} else {
new WorkerBootstrapper().start();
} Defensive patterns
Strategy: validation
Validate before calling
import { isMainThread } from 'node:worker_threads';
if (isMainThread) {
// main thread: run the manager, never the bootstrapper
} else {
new WorkerBootstrapper().start();
} Type guard
const canUseWorkerBootstrapper = () => !isMainThread;
Try / catch
let bootstrapper;
try {
bootstrapper = new WorkerBootstrapper();
} catch (err) {
if (err instanceof Error && /main thread/.test(err.message)) {
throw new Error('WorkerBootstrapper must live in the workerPath script, not the main entry');
} else throw err;
} Prevention
- Put WorkerBootstrapper instantiation only in the file referenced by the worker sharding strategy's workerPath.
- Follow the isMainThread branch pattern at the top of shared entry files.
- Use @discordjs/ws's own examples/templates for worker sharding layout.
When it happens
Trigger: Calling new WorkerBootstrapper() (or a subclass constructor) from the main entry file instead of from the file/module executed as a worker script, e.g. setting WorkerShardingStrategy's workerPath option to the same file that instantiates the bootstrapper on the main thread.
Common situations: Structuring a single entry file that both runs the bot and bootstraps workers without checking isMainThread; forgetting the main-thread guard pattern; copying the bootstrapper instantiation to the top of the workerPath script which the main thread also imports/executes.
Related errors
- Cannot instantiate WorkerContextFetchingStrategy on the main
- ShardingWorkerExists
- No worker found for shard ${shardId}
- Shard ${shardId} does not exist
- WebSocketShard: Compression is set to native zlib but node:z
AI-assisted analysis of discordjs/discord.js@a81ed8a306 (2026-08-30).
Data as JSON: /api/errors/ec32a3258ba8ede2.
Report an issue: GitHub.