I’m trying to create some slash commands for my discord bot, but there is an issue I can’t figure out while trying to deploy them. I’m using discord.js both to create the commands, via SlashCommandBuilder
, and to communicate with Discord, via the provided handler REST
.
I get this error whenever I try to launch the bot:
<code>c:PROJECT_PATHnode_modules@sapphireshapeshiftdistcjsindex.cjs:1469
return value instanceof this.expected ? Result.ok(value) : Result.err(new ExpectedValidationError("s.instance(V)", "Expected", value, this.expected));
ExpectedValidationError: Expected
at _InstanceValidator.handle (c:PROJECT_PATHnode_modules@sapphireshapeshiftdistcjsindex.cjs:1469:75)
at _InstanceValidator.parse (c:PROJECT_PATHnode_modules@sapphireshapeshiftdistcjsindex.cjs:939:90)
at assertReturnOfBuilder (c:PROJECT_PATHnode_modules@discordjsbuildersdistindex.js:1620:53)
at MixedClass._sharedAddOptionMethod (c:PROJECT_PATHnode_modules@discordjsbuildersdistindex.js:2382:5)
at MixedClass.addStringOption (c:PROJECT_PATHnode_modules@discordjsbuildersdistindex.js:2353:17)
at file:///c:/PROJECT_PATH/commands/utility/command0.js:24:10
at ModuleJob.run (node:internal/modules/esm/module_job:193:25)
at async Promise.all (index 0)
at async ESMLoader.import (node:internal/modules/esm/loader:530:24)
at async loadESM (node:internal/process/esm_loader:91:5) {
validator: 's.instance(V)',
expected: [Function: SlashCommandStringOption]
<code>c:PROJECT_PATHnode_modules@sapphireshapeshiftdistcjsindex.cjs:1469
return value instanceof this.expected ? Result.ok(value) : Result.err(new ExpectedValidationError("s.instance(V)", "Expected", value, this.expected));
^
ExpectedValidationError: Expected
at _InstanceValidator.handle (c:PROJECT_PATHnode_modules@sapphireshapeshiftdistcjsindex.cjs:1469:75)
at _InstanceValidator.parse (c:PROJECT_PATHnode_modules@sapphireshapeshiftdistcjsindex.cjs:939:90)
at assertReturnOfBuilder (c:PROJECT_PATHnode_modules@discordjsbuildersdistindex.js:1620:53)
at MixedClass._sharedAddOptionMethod (c:PROJECT_PATHnode_modules@discordjsbuildersdistindex.js:2382:5)
at MixedClass.addStringOption (c:PROJECT_PATHnode_modules@discordjsbuildersdistindex.js:2353:17)
at file:///c:/PROJECT_PATH/commands/utility/command0.js:24:10
at ModuleJob.run (node:internal/modules/esm/module_job:193:25)
at async Promise.all (index 0)
at async ESMLoader.import (node:internal/modules/esm/loader:530:24)
at async loadESM (node:internal/process/esm_loader:91:5) {
validator: 's.instance(V)',
given: undefined,
expected: [Function: SlashCommandStringOption]
}
Node.js v18.12.1
</code>
c:PROJECT_PATHnode_modules@sapphireshapeshiftdistcjsindex.cjs:1469
return value instanceof this.expected ? Result.ok(value) : Result.err(new ExpectedValidationError("s.instance(V)", "Expected", value, this.expected));
^
ExpectedValidationError: Expected
at _InstanceValidator.handle (c:PROJECT_PATHnode_modules@sapphireshapeshiftdistcjsindex.cjs:1469:75)
at _InstanceValidator.parse (c:PROJECT_PATHnode_modules@sapphireshapeshiftdistcjsindex.cjs:939:90)
at assertReturnOfBuilder (c:PROJECT_PATHnode_modules@discordjsbuildersdistindex.js:1620:53)
at MixedClass._sharedAddOptionMethod (c:PROJECT_PATHnode_modules@discordjsbuildersdistindex.js:2382:5)
at MixedClass.addStringOption (c:PROJECT_PATHnode_modules@discordjsbuildersdistindex.js:2353:17)
at file:///c:/PROJECT_PATH/commands/utility/command0.js:24:10
at ModuleJob.run (node:internal/modules/esm/module_job:193:25)
at async Promise.all (index 0)
at async ESMLoader.import (node:internal/modules/esm/loader:530:24)
at async loadESM (node:internal/process/esm_loader:91:5) {
validator: 's.instance(V)',
given: undefined,
expected: [Function: SlashCommandStringOption]
}
Node.js v18.12.1
As much as I understood, the problem should be at addStringOption
when building command0 but I can’t figure out where the validation fails. I made sure that the command name would have satisfied the regex required by Discord and the description is just a little string without anything particular.
Besides, I’d like to understand why there is a [Function: SlashCommandStringOption]
expected.
Here it is my app.js
<code>import { config } from 'dotenv';
import { REST, Routes, Client, Collection, Events, GatewayIntentBits } from 'discord.js';
import { commands } from './commands/commands.js';
const client = new Client({intents: [GatewayIntentBits.GuildMembers, GatewayIntentBits.Guilds]});
client.once(Events.ClientReady, readyClient => {
console.log(`Logged in as ${readyClient.user.tag}`);
// Setting up the possible commands of the client
client.commands = new Collection();
for (const name in commands) {
await client.commands.set(name, commands[name].default);
const rest = new REST().setToken(process.env.DISCORD_TOKEN);
console.log('Deploying (/) commands');
client.commands.toJSON().forEach(async element => {
const data = await rest.post(
Routes.applicationCommands(process.env.APP_ID),
'content-type':'application/json',
'Authorization':`Bot ${process.env.DISCORD_TOKEN}`,
console.log('Depoloyed (/) commands');
// Listener that execute interactions
client.on(Events.InteractionCreate, async interaction => {
if (!interaction.isChatInputCommand()) return;
const command = interaction.client.commands.get(interaction.commandName);
console.error(`No command matching ${interaction.commandName} found`);
await command.execute(interaction);
if (interaction.replied || interaction.deferred) {
await interaction.followUp({content: 'There was an error while executing this command!', ephemeral: true});
await interaction.reply({content: 'There was an error while executing this command!', ephemeral: true});
client.login(process.env.DISCORD_TOKEN);
<code>import { config } from 'dotenv';
import { REST, Routes, Client, Collection, Events, GatewayIntentBits } from 'discord.js';
import { commands } from './commands/commands.js';
config();
const client = new Client({intents: [GatewayIntentBits.GuildMembers, GatewayIntentBits.Guilds]});
client.once(Events.ClientReady, readyClient => {
console.log(`Logged in as ${readyClient.user.tag}`);
});
// Setting up the possible commands of the client
client.commands = new Collection();
for (const name in commands) {
await client.commands.set(name, commands[name].default);
}
const rest = new REST().setToken(process.env.DISCORD_TOKEN);
// Deploy of commands
(async () => {
try {
console.log('Deploying (/) commands');
client.commands.toJSON().forEach(async element => {
const data = await rest.post(
Routes.applicationCommands(process.env.APP_ID),
{
headers: {
'content-type':'application/json',
'Authorization':`Bot ${process.env.DISCORD_TOKEN}`,
},
body: element,
},
);
});
console.log('Depoloyed (/) commands');
} catch (error) {
console.error(error);
}
})();
// Listener that execute interactions
client.on(Events.InteractionCreate, async interaction => {
if (!interaction.isChatInputCommand()) return;
const command = interaction.client.commands.get(interaction.commandName);
if (!command) {
console.error(`No command matching ${interaction.commandName} found`);
return;
}
try {
await command.execute(interaction);
} catch (error) {
console.error(error);
if (interaction.replied || interaction.deferred) {
await interaction.followUp({content: 'There was an error while executing this command!', ephemeral: true});
} else {
await interaction.reply({content: 'There was an error while executing this command!', ephemeral: true});
}
}
});
client.login(process.env.DISCORD_TOKEN);
export {client};
</code>
import { config } from 'dotenv';
import { REST, Routes, Client, Collection, Events, GatewayIntentBits } from 'discord.js';
import { commands } from './commands/commands.js';
config();
const client = new Client({intents: [GatewayIntentBits.GuildMembers, GatewayIntentBits.Guilds]});
client.once(Events.ClientReady, readyClient => {
console.log(`Logged in as ${readyClient.user.tag}`);
});
// Setting up the possible commands of the client
client.commands = new Collection();
for (const name in commands) {
await client.commands.set(name, commands[name].default);
}
const rest = new REST().setToken(process.env.DISCORD_TOKEN);
// Deploy of commands
(async () => {
try {
console.log('Deploying (/) commands');
client.commands.toJSON().forEach(async element => {
const data = await rest.post(
Routes.applicationCommands(process.env.APP_ID),
{
headers: {
'content-type':'application/json',
'Authorization':`Bot ${process.env.DISCORD_TOKEN}`,
},
body: element,
},
);
});
console.log('Depoloyed (/) commands');
} catch (error) {
console.error(error);
}
})();
// Listener that execute interactions
client.on(Events.InteractionCreate, async interaction => {
if (!interaction.isChatInputCommand()) return;
const command = interaction.client.commands.get(interaction.commandName);
if (!command) {
console.error(`No command matching ${interaction.commandName} found`);
return;
}
try {
await command.execute(interaction);
} catch (error) {
console.error(error);
if (interaction.replied || interaction.deferred) {
await interaction.followUp({content: 'There was an error while executing this command!', ephemeral: true});
} else {
await interaction.reply({content: 'There was an error while executing this command!', ephemeral: true});
}
}
});
client.login(process.env.DISCORD_TOKEN);
export {client};
Here it is commands.js
<code>import * as command0 from "./utility/command0.js";
import * as comand1 from "./utility/command1.js";
export const commands = {
<code>import * as command0 from "./utility/command0.js";
import * as comand1 from "./utility/command1.js";
export const commands = {
'command0': command0,
'command1': command1,
};
</code>
import * as command0 from "./utility/command0.js";
import * as comand1 from "./utility/command1.js";
export const commands = {
'command0': command0,
'command1': command1,
};
command0.js
<code>import { SlashCommandBuilder } from "discord.js";
'data': new SlashCommandBuilder()
.setDescription('Description')
.setDescriptionLocalizations({
.addStringOption(option => {
.setDescriptionLocalizations({
.addUserOption(option => {
.setDescription('User to add')
.setDescriptionLocalizations({
it:'Utente da aggiungere',
'execute': async function(interaction) {
<code>import { SlashCommandBuilder } from "discord.js";
export default {
'data': new SlashCommandBuilder()
.setName('add')
.setNameLocalizations({
it:'aggiungi',
})
.setDescription('Description')
.setDescriptionLocalizations({
it:'Descrizione',
})
.addStringOption(option => {
option.setName('name')
.setNameLocalizations({
it:'nome',
})
.setDescription('Name')
.setDescriptionLocalizations({
it:'Nome',
})
.setRequired(true);
})
.addUserOption(option => {
option.setName('user')
.setNameLocalizations({
it:'utente',
})
.setDescription('User to add')
.setDescriptionLocalizations({
it:'Utente da aggiungere',
})
.setRequired(true);
}),
'execute': async function(interaction) {
// Execute stuff
}
};
</code>
import { SlashCommandBuilder } from "discord.js";
export default {
'data': new SlashCommandBuilder()
.setName('add')
.setNameLocalizations({
it:'aggiungi',
})
.setDescription('Description')
.setDescriptionLocalizations({
it:'Descrizione',
})
.addStringOption(option => {
option.setName('name')
.setNameLocalizations({
it:'nome',
})
.setDescription('Name')
.setDescriptionLocalizations({
it:'Nome',
})
.setRequired(true);
})
.addUserOption(option => {
option.setName('user')
.setNameLocalizations({
it:'utente',
})
.setDescription('User to add')
.setDescriptionLocalizations({
it:'Utente da aggiungere',
})
.setRequired(true);
}),
'execute': async function(interaction) {
// Execute stuff
}
};