discordjs/discord.js · error · Error

Tried to connect a shard that wasn't idle

Error message

Tried to connect a shard that wasn't idle

What it means

WebSocketShard.internalConnect() only makes sense from the Idle status. If the shard is already Connecting/Connected (or in another non-idle state) it throws to prevent a second WebSocket connection / identify for the same shard.

Source

Thrown at packages/ws/src/ws/WebSocketShard.ts:183

				once(this, WebSocketShardEvents.Resumed, { signal: controller.signal }),
			]);
		}

		void this.internalConnect();

		try {
			await promise;
		} finally {
			// cleanup hanging listeners
			controller.abort();
		}

		this.initialConnectResolved = true;
	}

	private async internalConnect() {
		if (this.#status !== WebSocketShardStatus.Idle) {
			throw new Error("Tried to connect a shard that wasn't idle");
		}

		const { version, encoding, compression, useIdentifyCompression } = this.strategy.options;
		this.identifyCompressionEnabled = useIdentifyCompression;

		const params = new URLSearchParams({ v: version, encoding });
		if (compression !== null) {
			if (useIdentifyCompression) {
				console.warn('WebSocketShard: transport compression is enabled, disabling identify compression');
				this.identifyCompressionEnabled = false;
			}

			params.append('compress', CompressionParameterMap[compression]);

			switch (compression) {
				case CompressionMethod.ZlibNative: {
					const zlib = await getNativeZlib();
					if (zlib) {

View on GitHub (pinned to a81ed8a306)

Solutions

  1. Ensure connect() is awaited and called only once per shard lifecycle
  2. Check shard.status === WebSocketShardStatus.Idle before calling connect()
  3. Don't manually connect a shard that the manager's strategy already manages — use manager.connect()
  4. On 'not idle' errors, inspect the status to decide whether to destroy({recover:true}) instead of connecting

Example fix

// before
await shard.connect();
// after
if (shard.status === WebSocketShardStatus.Idle) {
  await shard.connect();
}
Defensive patterns

Strategy: validation

Validate before calling

if (shard.status !== WebSocketShardStatus.Idle) {
  return; // already connecting/connected
}
await shard.connect();

Type guard

function canConnect(shard: WebSocketShard): boolean {
  return shard.status === WebSocketShardStatus.Idle;
}

Try / catch

try {
  await shard.connect();
} catch (e) {
  if (e instanceof Error && e.message.includes("wasn't idle")) {
    // already connecting — nothing to do
  } else throw e;
}

Prevention

When it happens

Trigger: Calling shard.connect() (or manager.connect() re-invoked) while the shard is already connecting or connected; internalConnect also being reachable via destroy() paths when the shard's status is not Idle.

Common situations: Calling connect() twice due to duplicate startup code or double event registration; race between an automatic resume/reconnect and a manual connect(); awaiting missing on an async connect call.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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