discordjs/discord.js · error · Error

Cannot instantiate WorkerContextFetchingStrategy on the main

Error message

Cannot instantiate WorkerContextFetchingStrategy on the main thread

What it means

WorkerContextFetchingStrategy is the WebSocket manager's fetching strategy that runs inside a worker_threads child worker and forwards session-info requests to the main thread over parentPort messaging. Its constructor checks isMainThread and throws immediately if instantiated on the main thread, because on the main thread there is no parentPort to communicate with and the MainContextFetchingStrategy should be used instead. The library offers both strategies and expects you to pick the correct one per environment.

Source

Thrown at packages/ws/src/strategies/context/WorkerContextFetchingStrategy.ts:22

import {
	WorkerReceivePayloadOp,
	WorkerSendPayloadOp,
	type WorkerReceivePayload,
	type WorkerSendPayload,
} from '../sharding/WorkerShardingStrategy.js';
import type { FetchingStrategyOptions, IContextFetchingStrategy } from './IContextFetchingStrategy.js';

export class WorkerContextFetchingStrategy implements IContextFetchingStrategy {
	private readonly sessionPromises = new Collection<number, (session: SessionInfo | null) => void>();

	private readonly waitForIdentifyPromises = new Collection<
		number,
		{ reject(error: unknown): void; resolve(): void; signal: AbortSignal }
	>();

	public constructor(public readonly options: FetchingStrategyOptions) {
		if (isMainThread) {
			throw new Error('Cannot instantiate WorkerContextFetchingStrategy on the main thread');
		}

		parentPort!.on('message', (payload: WorkerSendPayload) => {
			if (payload.op === WorkerSendPayloadOp.SessionInfoResponse) {
				this.sessionPromises.get(payload.nonce)?.(payload.session);
				this.sessionPromises.delete(payload.nonce);
			}

			if (payload.op === WorkerSendPayloadOp.ShardIdentifyResponse) {
				const promise = this.waitForIdentifyPromises.get(payload.nonce);
				if (payload.ok) {
					promise?.resolve();
				} else {
					// We need to make sure we reject with an abort error
					promise?.reject(promise.signal.reason);
				}

				this.waitForIdentifyPromises.delete(payload.nonce);

View on GitHub (pinned to a81ed8a306)

Solutions

  1. On the main thread use MainContextFetchingStrategy (or let createDefaultStrategy/fromSimpleShardingStrategy pick it) instead of WorkerContextFetchingStrategy.
  2. If you intend worker-based strategies, only construct WorkerContextFetchingStrategy inside code executed by a worker (via WorkerBootstrapper / worker_threads worker data).
  3. Use the library's provided strategy factories (e.g. createDefaultStrategy) rather than instantiating strategies manually so thread context is handled for you.

Example fix

// before (main entry file)
import { WorkerContextFetchingStrategy } from '@discordjs/ws';
const strategy = new WorkerContextFetchingStrategy(options);
// after
import { MainContextFetchingStrategy } from '@discordjs/ws';
const strategy = new MainContextFetchingStrategy(options);
// or inside worker code only:
// new WorkerContextFetchingStrategy(options) where !isMainThread
Defensive patterns

Strategy: validation

Validate before calling

import { isMainThread } from 'node:worker_threads';
import { WorkerContextFetchingStrategy, MainContextFetchingStrategy } from '@discordjs/ws';
function createStrategy(options) {
  return isMainThread
    ? new MainContextFetchingStrategy(options)
    : new WorkerContextFetchingStrategy(options);
}

Type guard

const isWorkerThread = () => !isMainThread;
if (isWorkerThread()) { /* safe to construct WorkerContextFetchingStrategy */ }

Try / catch

try {
  strategy = new WorkerContextFetchingStrategy(options);
} catch (err) {
  if (err instanceof Error && /main thread/.test(err.message)) {
    strategy = new MainContextFetchingStrategy(options);
  } else throw err;
}

Prevention

When it happens

Trigger: Calling new WorkerContextFetchingStrategy(options) in code executing on the main thread (isMainThread === true), e.g. passing it to WebSocketManager's retrieveSessionInfoStrategy/fetchGatewayInfoStrategy options from an entry script instead of from within the worker bootstrap.

Common situations: Misconfiguring the defaultShardingStrategy/strategy options so the manager builds a worker strategy in the main process; custom setup code copied from worker examples into the main entry file; running a script directly that was intended to be bootstrapped by WorkerBootstrapper.

Related errors


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