discordjs/discord.js · error · Error

No worker found for shard ${shardId}

Error message

No worker found for shard ${shardId}

What it means

WorkerShardingStrategy.send maps shardId to a worker via its #workerByShardId map and throws if no worker manages that shard. The mapping is populated during fetchShards/spawn, so an unmapped id means the shard was never assigned to any worker. Unlike SimpleShardingStrategy this throws a plain Error because the strategy has no direct shard objects to look up.

Source

Thrown at packages/ws/src/strategies/sharding/WorkerShardingStrategy.ts:182

				// eslint-disable-next-line no-promise-executor-return, promise/prefer-await-to-then
				new Promise<void>((resolve) => this.destroyPromises.set(shardId, resolve)).then(async () => worker.terminate()),
			);
			worker.postMessage(payload);
		}

		this.#workers = [];
		this.#workerByShardId.clear();

		await Promise.all(promises);
	}

	/**
	 * {@inheritDoc IShardingStrategy.send}
	 */
	public send(shardId: number, data: GatewaySendPayload) {
		const worker = this.#workerByShardId.get(shardId);
		if (!worker) {
			throw new Error(`No worker found for shard ${shardId}`);
		}

		const payload: WorkerSendPayload = {
			op: WorkerSendPayloadOp.Send,
			shardId,
			payload: data,
		};
		worker.postMessage(payload);
	}

	/**
	 * {@inheritDoc IShardingStrategy.fetchStatus}
	 */
	public async fetchStatus() {
		const statuses = new Collection<number, WebSocketShardStatus>();

		for (const [shardId, worker] of this.#workerByShardId.entries()) {
			const nonce = Math.random();

View on GitHub (pinned to a81ed8a306)

Solutions

  1. Await manager.spawn() (strategy.fetchShards) before sending any payloads so the worker-to-shard map is populated.
  2. Validate shardId against the configured shardCount/shardIds before calling send.
  3. If workers were killed, respawn via the manager instead of sending to stale ids.

Example fix

// before
await manager.send(shardId, { op: GatewayOpcodes.PresenceUpdate, ... });
// after
await manager.spawn();
if (shardId >= 0 && shardId < manager.totalShards) {
  await manager.send(shardId, { op: GatewayOpcodes.PresenceUpdate, ... });
}
Defensive patterns

Strategy: try-catch

Validate before calling

// With worker sharding, ensure spawn completed first:
await manager.spawn();
const total = manager.options.shardCount ?? 1;
if (!(shardId >= 0 && shardId < total)) {
  throw new RangeError(`shardId ${shardId} outside 0..${total - 1}`);
}

Type guard

const shardInRange = (id, total) => Number.isInteger(id) && id >= 0 && id < total;

Try / catch

try {
  await manager.send(shardId, payload);
} catch (err) {
  if (err instanceof Error && /No worker found for shard/.test(err.message)) {
    console.error(`No worker owns shard ${shardId}; did you await manager.spawn()?`);
  } else throw err;
}

Prevention

When it happens

Trigger: Calling send(shardId, payload) through the WebSocketManager while using the worker sharding strategy before spawn() has populated the worker map, with an out-of-range shardId, or after workers were destroyed/respawned and the map was cleared.

Common situations: Using WorkerShardingStrategy (workers: N > 0) with code written against the simple strategy that sends immediately at startup without awaiting spawn; mismatched shardIds computed from a different shard count; process restarts where spawn was skipped.

Related errors


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