Three years ago, I created a small Discord bot in Typescript that is now present on over 80 guilds. Recently, I made the decision to update it from discord.js-v12.3.1-dev
to discord.js-v13.6
, while also integrating the popular slash commands feature.
However, when I try to register these slash commands using discord.js's Routes.applicationGuildCommands
routine in my "ready" event by iterating over each Guild where my bot is active, I encounter an error message Missing Access
on most of the guilds (although not on all of them):
Trace: S[50001]: Missing Access
at Q.runRequest (/home/user/bot/node_modules/@discordjs/rest/src/lib/handlers/SequentialHandler.ts:487:11)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Q.queueRequest (/home/user/bot/node_modules/@discordjs/rest/src/lib/handlers/SequentialHandler.ts:200:11)
at async /home/user/bot/src/discord.ts:21:9
at async Promise.all (index 50)
at async Client.<anonymous> (/home/user/bot/src/discord.ts:19:5) {
rawError: { message: 'Missing Access', code: 50001 },
code: 50001,
status: 403,
method: 'put',
url: 'https://discord.com/api/v9/applications/642935463048642470/guilds/907457626412628088/commands',
requestBody: { files: undefined, json: [ [Object], [Object] ] }
}
at /home/user/bot/src/discord.ts:21:17
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Promise.all (index 50)
at async Client.<anonymous> (/home/user/bot/src/discord.ts:19:5)
Here is a snippet of my code (relevant parts only) showcasing the issue.
I am aware of the
Routes.applicationCommands
method, but it yields the same outcome. I prefer to individually push my commands to each guild for later translations on command descriptions.
import { Client, Intents, Guild } from 'discord.js';
import { REST } from '@discordjs/rest';
import { Routes } from 'discord-api-types/v9';
import * as commands from "./commands/";
export const bot: Client = new Client({
intents: [
Intents.FLAGS.GUILDS,
Intents.FLAGS.GUILD_MEMBERS,
Intents.FLAGS.GUILD_MESSAGES,
Intents.FLAGS.DIRECT_MESSAGES,
Intents.FLAGS.GUILD_MESSAGE_REACTIONS
]
});
bot.on("ready", async (): Promise<void> => {
const commandsList: any[] = Object.keys(commands)?.map((name: string) => commands[name]);
console.log(`Connected to (${bot.guilds.cache.size}) servers:`);
await Promise.all(bot.guilds.cache.map(async (guild: Guild) => {
try {
await rest.put(Routes.applicationGuildCommands(bot.user.id, guild.id), { body: commandsList });
console.log(` - ${guild.name} ✔️`);
} catch (error) {
console.log(` - ${guild.name} ❌`);
console.trace(error);
}
}));
console.log(`${commandsList.length} commands imported.`);
await bot.user.setActivity("le Krosmoz", { type: "WATCHING" });
});
The object commandsList
populated at the start of the ready
event is correct and structured like this:
commandsList = [
{
name: 'help',
description: 'Print the list of commands'
},
{
name: 'toto',
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit'
options: [
{
name: 'date',
description: "The toto's date",
type: 3,
required: false
},
{
name: 'item',
description: "The toto's item",
type: 3,
required: false
}
]
}
]
Although my code seems functional, not all guilds have the commands registered properly. The console displays a list of connected servers along with success or failure indicators like so:
Connected to (9) servers:
- Guild1 ❌
- Guild2 ✔️
- Guild3 ❌
- Guild4 ❌
- Guild5 ❌
- Guild6 ❌
- Guild7 ❌
- Guild8 ✔️
- Guild9 ❌
This output corresponds to either console.log(
- ${guild.name} ✔️);
or console.log(
- ${guild.name} ❌);
messages. A ❌
indicates encountering the Missing Access
error.
My question: How can I successfully register my slash commands across all guilds where my bot is present?
Some guilds show successful registration without actually having the commands available, even after attempting client reloads and waiting for extended periods. On the other hand, some guilds experiencing the Missing Access
error still display the registered commands.
While the absence of the applications.commands
initially led to issues when all guilds added my bot, similar bots like MEE6 and Tatsumaki managed to push their slash commands without requiring a kick-and-reinvite solution. Even granting admin permissions to my bot fails to ensure successful command registration on a test server.
I have thoroughly reviewed the "Application Commands" section of Discord Developer's Guide but found no conclusive answers. Suggestions on StackOverflow recommended adding the scope application.commands.update
(unavailable in my bot's portal).
Am I overlooking something?
I am hesitant to resort to kicking my bot from all guilds and reinviting it with the
applications.commands
scope, especially since multiple other bots managed to bypass this step.