discord.js: VoiceChannel.join uncatchable exceptions on failure to join
Please describe the problem you are having in as much detail as possible:
I have a voice channel recording bot. Recently I’ve noticed a few crashes because something has failed in VoiceChannel.join, but not gone to .catch (it just threw an exception that killed the whole process). It turns out that there is a class of errors joining the voice channel that throw uncatchable exceptions, ending the process entirely.
The problem is that the VoiceConnection emits an error before join’s then has ever been called, so no opportunity is given to catch the error. (Further, an error is a bit excessive for failing to join a voice channel)
Include a reproducible code sample here, if possible:
const fs = require("fs");
const Discord = require("discord.js");
const config = JSON.parse(fs.readFileSync("config.json", "utf8"));
var client = new Discord.Client();
client.on("message", (msg) => {
if (msg.content === "join" && msg.member && msg.member.voiceChannel) {
msg.member.voiceChannel.join().then(()=>{
msg.reply("Joined!");
}).catch((ex)=>{
msg.reply("Failed to join! " + ex);
});
}
});
client.on("voiceStateUpdate", (from, to) => {
if (to.guild && to.guild.voiceConnection)
to.guild.voiceConnection.disconnect();
});
client.login(config.token);
This example is obviously manufactured, but it was the only case I could find that will reliably crash. The crashes my bot is experiencing come from interactions that can’t be reliably reproduced. My voiceStateUpdate function is obviously ridiculous here, and just poisons the join, but the point is that the error it causes cannot be caught, so the whole bot crashes.
Further details:
Output with above code:
(node:21871) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: Tried to send join packet, but the WebSocket is not open.
(node:21871) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
events.js:183
throw er; // Unhandled 'error' event
^
Error: Error: Connection not established within 15 seconds.
at VoiceConnection.authenticateFailed (/home/yahweasel/craig-test/node_modules/discord.js/src/client/voice/VoiceConnection.js:258:26)
at connectTimeout.client.setTimeout (/home/yahweasel/craig-test/node_modules/discord.js/src/client/voice/VoiceConnection.js:280:18)
at Timeout.setTimeout (/home/yahweasel/craig-test/node_modules/discord.js/src/client/Client.js:422:7)
at ontimeout (timers.js:475:11)
at tryOnTimeout (timers.js:310:5)
at Timer.listOnTimeout (timers.js:270:5)
- discord.js version: 11.3.0
- node.js version: 8.9.4
- Operating system: Debian
- Priority this issue should have – please be realistic and elaborate if possible: Fairly serious, as I have no idea how to avoid the bug in normal code.
- I found this issue while running code on a user account
- I have also tested the issue on latest master, commit hash:
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 3
- Comments: 15 (5 by maintainers)
Another reliable way to evoke such an error: Join a voice channel, crash the bot (ctrl+c or whatever’s convenient), restart the bot and rejoin the channel quickly. It seems that if it’s still within that weird nether time where the disconnected bot shows as online and in the channel, it will fail to connect and raise the uncatchable error.
Literally could not be more irrelevant. Uncleanly disconnecting is not the bug. It is one reliable way to invoke the bug.
just use
process.on('SIGINT', () => <Client>.destroy());to intercept ctrl-c and pm2 restart/reload/stop cases.
Verification: It is indeed possible to race to get the voice connection before it raises an error:
So at least I can work around this without modifying discord.js. Still, I hope you agree this ain’t great code…