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

  1. Only instantiate WorkerBootstrapper inside the script referenced as the worker path (executed by worker_threads), wrapped in an if (!isMainThread) branch.
  2. On the main thread, construct WebSocketManager with WorkerShardingStrategy and pass options; let it spawn the workers that run the bootstrapper.
  3. 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

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


AI-assisted analysis of discordjs/discord.js@a81ed8a306 (2026-08-30). Data as JSON: /api/errors/ec32a3258ba8ede2. Report an issue: GitHub.