{"record":{"id":"fb4329ec43bd7156","repo":"discordjs/discord.js","slug":"resource-is-already-being-played-by-another-audio","errorCode":null,"errorMessage":"Resource is already being played by another audio player.","messagePattern":"Resource is already being played by another audio player\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/voice/src/audio/AudioPlayer.ts","lineNumber":388,"sourceCode":"\t * The player will transition to the Playing state once playback begins, and will return to the Idle state once\n\t * playback is ended.\n\t *\n\t * If the player was previously playing a resource and this method is called, the player will not transition to the\n\t * Idle state during the swap over.\n\t * @param resource - The resource to play\n\t * @throws Will throw if attempting to play an audio resource that has already ended, or is being played by another player\n\t */\n\tpublic play<Metadata>(resource: AudioResource<Metadata>) {\n\t\tif (resource.ended) {\n\t\t\tthrow new Error('Cannot play a resource that has already ended.');\n\t\t}\n\n\t\tif (resource.audioPlayer) {\n\t\t\tif (resource.audioPlayer === this) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthrow new Error('Resource is already being played by another audio player.');\n\t\t}\n\n\t\tresource.audioPlayer = this;\n\n\t\t// Attach error listeners to the stream that will propagate the error and then return to the Idle\n\t\t// state if the resource is still being used.\n\t\tconst onStreamError = (error: Error) => {\n\t\t\tif (this.state.status !== AudioPlayerStatus.Idle) {\n\t\t\t\tthis.emit('error', new AudioPlayerError(error, this.state.resource));\n\t\t\t}\n\n\t\t\tif (this.state.status !== AudioPlayerStatus.Idle && this.state.resource === resource) {\n\t\t\t\tthis.state = {\n\t\t\t\t\tstatus: AudioPlayerStatus.Idle,\n\t\t\t\t};\n\t\t\t}\n\t\t};\n","sourceCodeStart":370,"sourceCodeEnd":406,"githubUrl":"https://github.com/discordjs/discord.js/blob/a81ed8a306d37fdc746e26a634b6a42164ba2c8c/packages/voice/src/audio/AudioPlayer.ts#L370-L406","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nconst res = createAudioResource(stream);\nplayerA.play(res);\nplayerB.play(res); // throws\n// after\nplayerA.play(createAudioResource(stream1));\nplayerB.play(createAudioResource(stream2));","handlingStrategy":"validation","validationCode":"function canAssign(res, player) { return !res.audioPlayer || res.audioPlayer === player; }\nif (canAssign(res, playerB)) playerB.play(res); else res = createAudioResource(src);","typeGuard":"function isUnattached<T>(r: AudioResource<T>): boolean { return r.audioPlayer === undefined || r.audioPlayer === null; }","tryCatchPattern":"try { playerB.play(res); } catch (e) { if (e.message.includes('another audio player')) playerB.play(createAudioResource(src)); else throw e; }","preventionTips":["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"],"tags":["audio","resource-ownership","discord-voice"],"backgroundTag":"resource-already-in-use","analyzedSha":"a81ed8a306d37fdc746e26a634b6a42164ba2c8c","analyzedAt":"2026-08-30T04:07:22.193Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}