Heroku托管Discord.js反应角色机器人报Cannot read property 'execute'错误
报错场景
开发的带反应角色功能的Discord机器人,在Heroku托管环境下持续触发报错:TypeError: Cannot read property 'execute' of undefined
触发位置固定在代码行:client.commands.get('reactionrole').execute(message, args, Discord, client);
触发根因
代码中虽然初始化了命令集合容器client.commands = new Discord.Collection(),但完全没有将reactionrole.js对应的命令内容加载进这个集合。
集合内没有任何条目,执行client.commands.get('reactionrole')时会返回undefined,此时尝试读取undefined的.execute属性,就会直接抛出类型错误。这个问题和Heroku托管环境无关,是本地代码逻辑的缺失。
修复步骤
- 补全命令加载逻辑,两种方式二选一,写在
client.commands = new Discord.Collection();语句的下方即可:- 手动加载单文件写法(适合命令少的场景):直接require对应的命令文件,按名称存入集合
// 手动加载reactionrole命令 const reactionRoleCmd = require('./reactionrole.js'); client.commands.set(reactionRoleCmd.name, reactionRoleCmd); - 自动扫描目录写法(适合后续会加更多命令的场景):先在根目录新建
commands文件夹,把所有命令文件移入该文件夹,再执行扫描逻辑// 扫描commands目录下所有js格式的命令文件 const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js')); // 将每个命令按名称存入集合 for (const file of commandFiles) { const command = require(`./commands/${file}`); client.commands.set(command.name, command); }
- 手动加载单文件写法(适合命令少的场景):直接require对应的命令文件,按名称存入集合
- 给命令触发逻辑加上基础容错,避免后续再加命令时出现同类报错,将原消息监听内的reactionrole触发逻辑替换为带判空的版本:
} else if (command === 'reactionrole') { const targetCommand = client.commands.get('reactionrole'); if (!targetCommand) return message.reply('对应指令加载失败,请检查项目配置'); targetCommand.execute(message, args, Discord, client); }
补充注意事项:当前代码将
messageReactionAdd、messageReactionRemove两个事件监听写在了reactionrole指令的execute函数内部,只要有人触发一次该指令,就会重复注册一次全局事件,长期运行会出现角色重复添加、重复移除的逻辑bug,建议将这两个事件的处理逻辑移出指令执行函数,放到main.js的全局事件监听位置,避免重复绑定。
内容的提问来源于stack exchange,提问作者user15132053
相关产品推荐
相关产品推荐

