discord.js执行/warn remove报user参数类型STRING预期USER错误
问题现象
基于discord.js开发Discord机器人时,调用/warn remove斜杠子命令持续抛出TypeError [COMMAND_INTERACTION_OPTION_TYPE]类型错误:提示名为user的选项类型为STRING,预期类型应为USER。报错堆栈定位到代码第69行第42列位置,自行排查未找到根因,触发报错的相关代码段如下:
module.exports = { category: 'Moderation', description: 'Warn a user', permissions: ['ADMINISTRATOR'], slash: true, guildOnly: true, options: [ { type: 'SUB_COMMAND', name: 'remove', description: 'Removes a warning from the user', options: [ { name: 'user', type: 'USER', description: 'The user to remove the warning from', required: true, }, { name: 'id', type: 'STRING', description: 'The ID of the warning to remove', required: true, }, ], } ], callback: async ({ guild, member: staff, interaction }) => { const user = interaction.options.getUser('user') if (subCommand === 'remove') { const warning = await warnSchema.findByIdAndDelete(id) return { custom: true, content: `Removed warning ${warning.id} from <@${user?.id}>`, allowedMentions: { users: [] } } } } }
报错根因
- 斜杠命令选项的
type字段传值错误:discord.js 不识别'SUB_COMMAND'/'USER'/'STRING'这类字符串类型值,必须使用官方枚举ApplicationCommandOptionType对应的固定值。传字符串时框架无法正确向Discord注册USER类型选项,Discord端会默认将该参数按STRING类型解析,调用getUser()方法取值时就会触发类型不匹配错误。 - 回调函数存在未定义变量:代码中直接使用
subCommand、id两个变量,没有提前从interaction实例中解析对应值,就算修复类型问题,运行时也会抛出变量未定义的引用错误。另外user参数属于remove子命令下的嵌套选项,直接在子命令判断逻辑外取值,也可能出现跨子命令取参的异常。
修复方案
- 从discord.js中引入
ApplicationCommandOptionType枚举,替换所有选项的type字段值为对应枚举项 - 回调逻辑中先解析当前触发的子命令,在匹配到
remove子命令后,再解析该子命令下的user、id参数值 - 修改命令配置后重启机器人,等待斜杠命令注册缓存更新(全局命令更新最长需要1小时,测试阶段可注册为服务器专属命令,更新即时生效)
修复后的核心代码如下:
const { ApplicationCommandOptionType } = require('discord.js'); module.exports = { category: 'Moderation', description: 'Warn a user', permissions: ['ADMINISTRATOR'], slash: true, guildOnly: true, options: [ { type: ApplicationCommandOptionType.Subcommand, name: 'remove', description: 'Removes a warning from the user', options: [ { name: 'user', type: ApplicationCommandOptionType.User, description: 'The user to remove the warning from', required: true, }, { name: 'id', type: ApplicationCommandOptionType.String, description: 'The ID of the warning to remove', required: true, }, ], } ], callback: async ({ guild, member: staff, interaction }) => { const subCommand = interaction.options.getSubcommand(); if (subCommand === 'remove') { const user = interaction.options.getUser('user'); const id = interaction.options.getString('id'); const warning = await warnSchema.findByIdAndDelete(id); return { custom: true, content: `Removed warning ${warning.id} from <@${user?.id}>`, allowedMentions: { users: [] } } } } }
内容的提问来源于stack exchange,提问作者user17646297
相关产品推荐
相关产品推荐

