{"record":{"id":"3bfd437ec1c57b8f","repo":"discordjs/discord.js","slug":"unsupported-decryption-method-mode","errorCode":null,"errorMessage":"Unsupported decryption method: ${mode}","messagePattern":"Unsupported decryption method: (.+?)","errorType":"exception","errorClass":"RangeError","httpStatus":null,"severity":"error","filePath":"packages/voice/src/receive/VoiceReceiver.ts","lineNumber":128,"sourceCode":"\t\t\t\tdecipheriv.setAuthTag(authTag);\n\n\t\t\t\treturn Buffer.concat([decipheriv.update(encrypted), decipheriv.final()]);\n\t\t\t}\n\n\t\t\tcase 'aead_xchacha20_poly1305_rtpsize': {\n\t\t\t\t// Combined mode expects authtag in the encrypted message\n\t\t\t\treturn Buffer.from(\n\t\t\t\t\tmethods.crypto_aead_xchacha20poly1305_ietf_decrypt(\n\t\t\t\t\t\tBuffer.concat([encrypted, authTag]),\n\t\t\t\t\t\theader,\n\t\t\t\t\t\tnonce,\n\t\t\t\t\t\tsecretKey,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tthrow new RangeError(`Unsupported decryption method: ${mode}`);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Parses an audio packet, decrypting it to yield an Opus packet.\n\t *\n\t * @param rtp - The incoming RTP packet buffer to be parsed\n\t * @param mode - The encryption mode\n\t * @param nonce - The nonce buffer used by the connection for encryption\n\t * @param secretKey - The secret key used by the connection for encryption\n\t * @param userId - The user id that sent the packet\n\t * @param ssrc - already-parsed SSRC (Synchronization Source Identifier) from the RTP Header\n\t * @returns Decrypted Opus payload and RTP header information, or null if DAVE decrypt failed in a way that should be ignored\n\t */\n\tprivate parsePacket(\n\t\trtp: Buffer,\n\t\tmode: string,","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/discordjs/discord.js/blob/a81ed8a306d37fdc746e26a634b6a42164ba2c8c/packages/voice/src/receive/VoiceReceiver.ts#L110-L146","documentation":"VoiceReceiver.decrypt throws this RangeError when the receiver's decryption mode string does not match any branch of its switch. The mode comes from the negotiated encryption mode stored on the receiver, so this means the library instance cannot decrypt with the mode the voice connection selected — typically because the installed version predates that mode. Like error 320, the default branch is expected to be unreachable in a healthy negotiation.","triggerScenarios":"Connecting a VoiceReceiver to a voice connection whose negotiated encryption mode is unknown to the installed @discordjs/voice version (e.g. aead_xchacha20_poly1305_rtpsize on an older libsodium-only build), or passing a bogus mode directly when calling decrypt manually.","commonSituations":"Outdated @discordjs/voice after Discord rolled out new encryption modes; mismatch between the connection's negotiated mode and the receiver's expectations; custom code invoking decrypt with a hand-crafted mode value.","solutions":["Update @discordjs/voice to the latest version so the new encryption mode is supported for receiving.","Ensure the installed crypto packages (sodium / libsodium-wrappers / @stablelib/xchacha20poly1305 / @noble/ciphers) match the mode requirements of the current version.","Log mode (this.mode / negotiated mode) to confirm which unsupported value triggered the throw.","Restrict gateway modes via library config or rejoin the voice channel to renegotiate a supported mode."],"exampleFix":"// before\nconst audio = receiver.subscribe(userId); // receiver.decrypt throws for new mode on old version\n// after\n// npm i @discordjs/voice@latest  (handles aead_xchacha20_poly1305_rtpsize)\nconst audio = receiver.subscribe(userId);","handlingStrategy":"try-catch","validationCode":"// Before wiring the receiver, verify the negotiated mode is decryptable:\nconst DECRYPTABLE = ['aead_xchacha20_poly1305_rtpsize', 'xsalsa20_poly1305_lite', 'xsalsa20_poly1305_suffix', 'xsalsa20_poly1305'];\nif (!DECRYPTABLE.includes(negotiatedMode)) console.warn('Receiver cannot decrypt with mode', negotiatedMode, '- update @discordjs/voice');","typeGuard":"function isDecryptableMode(mode: string): boolean {\n  return ['aead_xchacha20_poly1305_rtpsize', 'xsalsa20_poly1305_lite', 'xsalsa20_poly1305_suffix', 'xsalsa20_poly1305'].includes(mode);\n}","tryCatchPattern":"try {\n  const ssrc = receiver.ssrcMap.get(userId);\n  // packet processing\n} catch (e) {\n  if (e instanceof RangeError && e.message.startsWith('Unsupported decryption method')) {\n    console.error('Mode mismatch:', e.message); // alert / rejoin with supported mode\n  } else throw e;\n}","preventionTips":["Update @discordjs/voice whenever Discord changes encryption modes.","Recreate the receiver when the voice connection is renegotiated so mode and key stay in sync.","Install the crypto packages required by the negotiated mode (xchacha20 for the AEAD mode).","Log the negotiated mode at startup to detect mismatches early."],"tags":["encryption","voice","decryption","range-error"],"backgroundTag":"unsupported-encryption-mode","analyzedSha":"a81ed8a306d37fdc746e26a634b6a42164ba2c8c","analyzedAt":"2026-08-30T04:07:22.193Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}