Discord.js踢人命令报错:TypeError: Cannot read properties of null (reading 'roles')
Discord 踢人命令报错修复方案
问题背景
跟着reconlx的踢人、封禁与解封命令教程开发踢人命令,但所有命令(包括踢人命令)均无法正常运行,以下是相关代码及报错信息:
kick.js 代码
const { MessageEmbed, Message } = require("discord.js"); module.exports = { name: 'kick', description: 'Kicks a member', userPermissions: ["KICK_MEMBERS"], options: [ { name: "member", description: "The member you wish to kick", type: "USER", required: true }, { name: "reason", description: "Reason for kicking", type: "STRING", required: false }, ], /** * @param {Client} client * @param {CommandInteraction} interaction * @param {String[]} args */ run: async (client, interaction, args) => { const target = interaction.options.getMember("target"); const reason = interaction.options.getString("reason") || "No reason(s) provided"; const rolePositionCheck = new MessageEmbed() .setTitle("You can't kick a person with a higher role than yours!") .setFooter({ text: "Error: Lower Role Position"}) if ( target.roles.highest.position >= interaction.member.roles.highest.position ) return interaction.followUp({ embeds: [rolePositionCheck], }); // Message which is sent to the person kicked const kickMessage = new MessageEmbed() .setTitle(`You've been kicked from ${interaction.guild.name}`) .setFooter({ text: `Reason: ${reason}` }) await target.send({ embeds: [kickMessage] }); // The action of kicking, along with the reason target.kick(reason) // Message which is sent to the mod who kicked. const kickAftermath = new MessageEmbed() .setTitle(`${target.user.tag} has been kicked!`) .setFooter({ text: `${reason}` }) interaction.followUp({ embeds: [kickAftermath], }); }, };
报错信息
TypeError: Cannot read properties of null (reading 'roles') at Object.run (C:\Users\admin\Desktop\Tonkotsu\SlashCommands\moderation\kick.js:38:20) at Client.<anonymous> (C:\Users\admin\Desktop\Tonkotsu\events\interactionCreate.js:27:13) at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
问题分析
报错指向target.roles,说明target变量为null。核心原因是代码中获取成员时使用的参数名是"target",但命令定义的参数名是"member",两者不匹配,导致interaction.options.getMember()返回null,后续访问roles属性时触发报错。
修复步骤
- 修正参数名匹配问题
将代码中获取目标成员的行:
const target = interaction.options.getMember("target");
修改为:
const target = interaction.options.getMember("member");
确保参数名与命令定义的options[0].name完全一致。
- 增加空值判断
为避免因目标成员不在服务器中导致的报错,在获取target后添加判断逻辑:
if (!target) { return interaction.followUp({ content: "该成员不在当前服务器中,无法执行踢人操作!" }); }
- 异步操作添加await
target.kick()是异步方法,添加await确保踢人操作完成后再发送结果消息,避免逻辑顺序混乱:
await target.kick(reason);
- 处理私信发送失败场景
添加try-catch包裹私信发送逻辑,避免因成员关闭私信导致命令中断:
try { await target.send({ embeds: [kickMessage] }); } catch (err) { console.log(`无法给${target.user.tag}发送私信:`, err); }
修改后的完整代码
const { MessageEmbed } = require("discord.js"); module.exports = { name: 'kick', description: '踢出成员', userPermissions: ["KICK_MEMBERS"], options: [ { name: "member", description: "你想要踢出的成员", type: "USER", required: true }, { name: "reason", description: "踢出理由", type: "STRING", required: false }, ], /** * @param {Client} client * @param {CommandInteraction} interaction * @param {String[]} args */ run: async (client, interaction, args) => { const target = interaction.options.getMember("member"); const reason = interaction.options.getString("reason") || "未提供理由"; // 检查目标成员是否存在 if (!target) { return interaction.followUp({ content: "该成员不在当前服务器中,无法执行踢人操作!" }); } const rolePositionCheck = new MessageEmbed() .setTitle("无法踢出角色等级高于你的成员!") .setFooter({ text: "错误:角色等级不足"}) if (target.roles.highest.position >= interaction.member.roles.highest.position) { return interaction.followUp({ embeds: [rolePositionCheck] }); } // 发送给被踢成员的消息 const kickMessage = new MessageEmbed() .setTitle(`你已被从${interaction.guild.name}踢出`) .setFooter({ text: `原因:${reason}` }) try { await target.send({ embeds: [kickMessage] }); } catch (err) { // 处理无法发送消息的情况(如成员关闭了私信) console.log(`无法给${target.user.tag}发送私信:`, err); } // 执行踢人操作 await target.kick(reason); // 发送给执行操作的管理员的消息 const kickAftermath = new MessageEmbed() .setTitle(`${target.user.tag} 已被踢出!`) .setFooter({ text: `${reason}` }) await interaction.followUp({ embeds: [kickAftermath] }); }, };
内容的提问来源于stack exchange,提问作者user18575297
相关产品推荐
相关产品推荐

