discord.js V12 addrole命令报role.id相关错误排查
问题背景
discord.js升级至V13版本后,自行开发的Discord机器人addrole命令无法正常运行,执行时抛出role.id is not a function、role.id is not defined类错误。开发者具备较丰富JavaScript开发经验,确认自身代码逻辑无明显问题,尝试多种修复方案均未生效,初步怀疑故障与V12版本废弃后Discord API调用规则变动有关。
故障命令原实现代码如下:
const lineReplyNoMention = require('discord-reply'); const color = process.env.Color; module.exports = { name: 'addrole', cooldown: 5, aliases: ['addnewrole'], permissions: ["MANAGE_ROLES"], clientpermissions: ["MANAGE_ROLES", "SEND_MESSAGES", "EMBED_LINKS"], async execute(client, message, cmd, args, Discord) { const user = message.mentions.users.first(); const usertarget = message.guilds.members.cache.get(user.id); if (!user) { const nopr = new Discord.MessageEmbed().setTimestamp().setColor(`${color}`).setAuthor(`${message.author.username}`, message.author.displayAvatarURL({ dynamic: true })).setDescription(`**\`(prefix)addrole <@user> <@role>\`**`) return message.lineReplyNoMention({ embed: nopr }) } args.shift() const roleToGive = message.mentions.roles.first() if (!roleToGive) { const addroleError2 = new Discord.MessageEmbed().setTimestamp().setDescription(`**No Roles Provided!**`).setColor(`${color}`) return message.lineReplyNoMention({ embed: addroleError2 }) } usertarget.roles.add(roleToGive.id) const embed = new Discord.MessageEmbed().setTimestamp().setColor(`${color}`).setAuthor(`${message.author.username}`, message.author.displayAvatarURL({ dynamic: true })).setDescription(`**Added: \`${roleToGive}\` To \`${user.username}\`**`) message.lineReplyNoMention({ embed: embed }) } }
故障根因
代码存在4处和V13版本不兼容/书写错误的问题,和V12版本废弃无直接关联:
- 基础拼写错误:获取目标服务器成员时使用了
message.guilds.members.cache,discord.js中单条消息所属的服务器对象属性为单数形式message.guild,message.guilds是客户端级别的所有服务器缓存,在消息对象上直接调用会返回undefined,后续读取成员属性自然会报未定义错误。 - 边界判断缺失:代码未判断目标成员对象是否真实存在,如果提及的用户不在当前服务器内,后续执行加角色操作时会直接触发属性读取错误。
- V13接口适配遗漏:discord.js V13调整了消息发送参数格式,原V12版本中传入单embed的
embed字段,在V13中改为复数形式embeds,要求传入embed数组;同时roles.add()是异步方法,原代码未加await也未做错误捕获,执行时序异常时也会触发报错。 - 第三方依赖兼容问题:使用的
discord-reply包如果是适配V12的旧版本,在V13运行环境下会破坏message对象原型链,间接导致角色、成员相关属性读取失败。
修复方案
- 将
message.guilds修正为message.guild - 补充目标成员存在性判断
- 适配V13消息发送参数格式,将所有
embed字段替换为embeds数组 - 给异步的加角色方法添加await和错误捕获
- 如果
discord-reply包运行异常,可以直接用原生message.reply配合allowedMentions参数实现不@回复效果,无需额外依赖 - 补充机器人角色层级判断,避免因角色权限不足触发API报错
修复后可正常运行的代码如下:
const color = process.env.Color; module.exports = { name: 'addrole', cooldown: 5, aliases: ['addnewrole'], permissions: ["MANAGE_ROLES"], clientpermissions: ["MANAGE_ROLES", "SEND_MESSAGES", "EMBED_LINKS"], async execute(client, message, cmd, args, Discord) { const user = message.mentions.users.first(); if (!user) { const nopr = new Discord.MessageEmbed() .setTimestamp() .setColor(color) .setAuthor(message.author.username, message.author.displayAvatarURL({ dynamic: true })) .setDescription(`**\`(prefix)addrole <@user> <@role>\`**`) return message.reply({ embeds: [nopr], allowedMentions: { repliedUser: false } }) } // 修正guild拼写,补充成员存在判断 const usertarget = message.guild.members.cache.get(user.id); if (!usertarget) { const noMember = new Discord.MessageEmbed() .setTimestamp() .setColor(color) .setDescription(`**目标用户不在当前服务器内**`) return message.reply({ embeds: [noMember], allowedMentions: { repliedUser: false } }) } args.shift() const roleToGive = message.mentions.roles.first() if (!roleToGive) { const addroleError2 = new Discord.MessageEmbed() .setTimestamp() .setDescription(`**未提供要添加的角色**`) .setColor(color) return message.reply({ embeds: [addroleError2], allowedMentions: { repliedUser: false } }) } // 补充角色位置权限判断,避免权限不足报错 if (message.guild.me.roles.highest.position <= roleToGive.position) { const permErr = new Discord.MessageEmbed() .setTimestamp() .setDescription(`**机器人角色权限不足,无法分配该角色**`) .setColor(color) return message.reply({ embeds: [permErr], allowedMentions: { repliedUser: false } }) } await usertarget.roles.add(roleToGive.id).catch(e => { const errEmbed = new Discord.MessageEmbed() .setTimestamp() .setDescription(`**添加角色失败:${e.message}**`) .setColor(color) return message.reply({ embeds: [errEmbed], allowedMentions: { repliedUser: false } }) }) const embed = new Discord.MessageEmbed() .setTimestamp() .setColor(color) .setAuthor(message.author.username, message.author.displayAvatarURL({ dynamic: true })) .setDescription(`**已将角色 \`${roleToGive.name}\` 分配给 \`${user.username}\`**`) message.reply({ embeds: [embed], allowedMentions: { repliedUser: false } }) } }
注意:运行V13版本discord.js时,需要在客户端初始化时开启
GUILDS、GUILD_MEMBERS、GUILD_MESSAGES、GUILD_ROLES相关Intents,同时在Discord开发者后台开启对应服务器成员权限开关,否则缓存无法正常加载成员、角色数据。
内容的提问来源于stack exchange,提问作者Brandon Torreglosa
相关产品推荐
相关产品推荐

