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
- Create a separate AudioResource per AudioPlayer
- Stop the old player / unsubscribe the resource before reassigning
- Set resource.audioPlayer = undefined only if you truly intend to detach (and the stream is still readable)
- 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
- One AudioResource per AudioPlayer, always
- Detach/unsubscribe from the old player before reassigning
- Avoid storing a single resource in shared state across connections
- Recreate resources when migrating playback between channels
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
- Cannot play a resource that has already ended.
- Invalid pipeline constructed for string resource '${input}'
- Node type '${type}' does not exist!
- Cannot play audio as no valid encryption package is installe
AI-assisted analysis of discordjs/discord.js@a81ed8a306 (2026-08-30).
Data as JSON: /api/errors/fb4329ec43bd7156.
Report an issue: GitHub.