I have a Discord bot using discord.js. Since I implemented slash commands, if the server is down when fetching files from it, it'll make my bot crash. I've tried a number of things but I can't seem for the life of me to figure out how to catch the error properly.
Here's the code of my command:
<!-- language: js -->
const { SlashCommandBuilder } = require('@discordjs/builders');
module.exports = {
data: new SlashCommandBuilder()
.setName('fetchtest')
.setDescription('Fetch GTA:SA files.')
.addSubcommand(gta3Cmd =>
gta3Cmd
.setName('gta3')
.setDescription('Fetch files from gta3.img')
.addStringOption(option => option.setName('file').setRequired(true).setDescription('File to fetch from database.')))
.addSubcommand(playerCmd =>
playerCmd
.setName('player')
.setDescription('Fetch files from player.img')
.addStringOption(option => option.setName('file').setRequired(true).setDescription('File to fetch from database.'))),
async execute(interaction) {
let imageFile;
if (interaction.options.getSubcommand() === 'gta3') {
imageFile = 'gta3';
}
else if (interaction.options.getSubcommand() === 'player') {
imageFile = 'player';
}
await interaction.client.fetch(`${interaction.client.config.gtaApiServer}/api/v1/gta/sa/${imageFile}?title=${interaction.options.getString('file')}`)
.then((fetchGameFile) => {
if (fetchGameFile.ok) {
const gameFileData = fetchGameFile.json();
let hasReturned = false;
if (gameFileData[0].urlDFF != undefined) {
interaction.reply({
files: [
gameFileData[0].urlDFF,
],
});
hasReturned = true;
}
if (hasReturned === true && gameFileData[0].urlTXD != undefined) {
interaction.followUp({
files: [
gameFileData[0].urlTXD,
],
});
}
else if (hasReturned === false && gameFileData[0].urlTXD != undefined) {
interaction.reply({
files: [
gameFileData[0].urlTXD,
],
});
}
else {
interaction.reply(`File with name ${interaction.options.getString('file')} not found.`);
return;
}
}
else {
return interaction.reply('Server is down');
}
});
},
};
This triggers the following errors:
FetchError: request to http://serverip/api/v1/gta/sa/gta3?title=fam2 failed, reason: connect ETIMEDOUT serverip
at ClientRequest.<anonymous> (C:\Projects\klochon\node_modules\node-fetch\lib\index.js:1461:11)
at ClientRequest.emit (node:events:394:28)
at Socket.socketErrorListener (node:_http_client:447:9)
at Socket.emit (node:events:394:28)
at emitErrorNT (node:internal/streams/destroy:157:8)
at emitErrorCloseNT (node:internal/streams/destroy:122:3)
at processTicksAndRejections (node:internal/process/task_queues:83:21) {
type: 'system',
errno: 'ETIMEDOUT',
code: 'ETIMEDOUT'
}
C:\Projects\klochon\node_modules\discord.js\src\rest\RequestHandler.js:298
throw new DiscordAPIError(data, res.status, request);
^
DiscordAPIError: Unknown interaction
at RequestHandler.execute (C:\Projects\klochon\node_modules\discord.js\src\rest\RequestHandler.js:298:13)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async RequestHandler.push (C:\Projects\klochon\node_modules\discord.js\src\rest\RequestHandler.js:50:14)
at async CommandInteraction.reply (C:\Projects\klochon\node_modules\discord.js\src\structures\interfaces\InteractionResponses.js:99:5)
at async Client.<anonymous> (C:\Projects\klochon\index.js:51:3) {
method: 'post',
path: '/interactions/881934786988499044/aW50ZXJhY3Rpb246ODgxOTM0Nzg2OTg4NDk5MDQ0OjRvUWMzeHVnQzl2QjlIM2tqRVZpSENmTTlkQ1FWYUE1dHFac1JaTWdTcjE2UWZZaXFKYWk2eXppZkM5cE9GcW5HQUdLNnN4UDZXcU5JR2JCelljQUxDdHNJUktpUzdwRmZzYnRzcVZKNFIzczB6MDRHVXlGYndtb0J0a2RzSDZj/callback',
code: 10062,
httpStatus: 404,
requestData: {
json: {
type: 4,
data: {
content: 'There was an error while executing this command!',
tts: false,
nonce: undefined,
embeds: undefined,
components: undefined,
username: undefined,
avatar_url: undefined,
allowed_mentions: undefined,
flags: 64,
message_reference: undefined,
attachments: undefined,
sticker_ids: undefined
}
},
files: []
}
}
I've read examples on how to catch errors when fetching but nothing seems to work. Occasionally it stopped the crashing but the bot wouldn't reply or I'd get no console.log response. I'd appreciate any tips, thank you.
Your fetch
is likely returning a Promise that is rejected due to the server being down. Since you are using await
, this results in a JavaScript error.
If you want to handle a rejected Promise using async/await, then you need to use a try/catch block.
try {
await fetch(...)
} catch(e) {
// e is the rejected promise reason, usually an error
}
See MDN's "Promise rejection" for more info.