discordjs/discord.js · error · Error

Resource is already being played by another audio player.

Error message

Resource is already being played by another audio player.

What it means

An AudioResource can only be attached to one AudioPlayer at a time. play() throws if resource.audioPlayer is set to a different player, to prevent two players interleaving reads from the same stream. Calling play() with the same resource on the same player is a no-op (returns).

Source

Thrown at packages/voice/src/audio/AudioPlayer.ts:388

	 * The player will transition to the Playing state once playback begins, and will return to the Idle state once
	 * playback is ended.
	 *
	 * If the player was previously playing a resource and this method is called, the player will not transition to the
	 * Idle state during the swap over.
	 * @param resource - The resource to play
	 * @throws Will throw if attempting to play an audio resource that has already ended, or is being played by another player
	 */
	public play<Metadata>(resource: AudioResource<Metadata>) {
		if (resource.ended) {
			throw new Error('Cannot play a resource that has already ended.');
		}

		if (resource.audioPlayer) {
			if (resource.audioPlayer === this) {
				return;
			}

			throw new Error('Resource is already being played by another audio player.');
		}

		resource.audioPlayer = this;

		// Attach error listeners to the stream that will propagate the error and then return to the Idle
		// state if the resource is still being used.
		const onStreamError = (error: Error) => {
			if (this.state.status !== AudioPlayerStatus.Idle) {
				this.emit('error', new AudioPlayerError(error, this.state.resource));
			}

			if (this.state.status !== AudioPlayerStatus.Idle && this.state.resource === resource) {
				this.state = {
					status: AudioPlayerStatus.Idle,
				};
			}
		};

View on GitHub (pinned to a81ed8a306)

Solutions

  1. Create a separate AudioResource per AudioPlayer
  2. Stop the old player / unsubscribe the resource before reassigning
  3. Set resource.audioPlayer = undefined only if you truly intend to detach (and the stream is still readable)
  4. Share the source file/URL and build one resource per destination

Example fix

// before
const res = createAudioResource(stream);
playerA.play(res);
playerB.play(res); // throws
// after
playerA.play(createAudioResource(stream1));
playerB.play(createAudioResource(stream2));
Defensive patterns

Strategy: validation

Validate before calling

function canAssign(res, player) { return !res.audioPlayer || res.audioPlayer === player; }
if (canAssign(res, playerB)) playerB.play(res); else res = createAudioResource(src);

Type guard

function isUnattached<T>(r: AudioResource<T>): boolean { return r.audioPlayer === undefined || r.audioPlayer === null; }

Try / catch

try { playerB.play(res); } catch (e) { if (e.message.includes('another audio player')) playerB.play(createAudioResource(src)); else throw e; }

Prevention

When it happens

Trigger: Passing an AudioResource to AudioPlayer B while it is still assigned to AudioPlayer A (resource.audioPlayer points elsewhere); e.g. moving a resource between voice connections without unsubscribing/recreating it.

Common situations: Migrating playback between voice connections/channels reusing the same resource; playing one stream into two guilds; holding a shared resource in a queue consumed by multiple players.

Related errors


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