如何让Bot向指定用户发送DM,解决调用send方法时null属性读取报错问题
问题原因
报错核心是user变量实际为null时调用了send方法导致的。你给client.users.fetch加了catch返回null的逻辑,只要用户拉取失败(比如用户ID无效、机器人无权限拉取该用户、缓存未命中且你设置了不请求API),user就会是null,未加判断直接调用方法就会抛出该错误。
另外你的代码还有一个隐藏问题:user.send({ embeds: embed })参数格式错误,embeds字段要求传入数组,直接传单个Embed对象就算user存在也会触发参数错误。
修复方案
// 先拉取用户,第二个参数改为true强制请求API,避免缓存miss导致有效ID返回null const user = await client.users .fetch(interaction.options.getString("user"), true) .catch(() => null); console.log(interaction.options.getString("user")); const embed = new MessageEmbed() .setColor("#FCE100") .setTitle(`⚠️ Warning!`) .setDescription(interaction.options.getString("warning")); // 先判断用户是否存在,不存在直接回复错误 if (!user) { // 优先用interaction.reply回复,避免交互超时,如果已经defer可以换成followUp await interaction.reply({ content: "Error: user not found", ephemeral: true }); return; } // 给embeds参数套数组,符合discord.js的参数要求 await user.send({ embeds: [embed] }).catch(async () => { // 用户关闭了DM权限的情况也返回对应提示 await interaction.reply({ content: "Error: cannot send DM to this user", ephemeral: true }); });
关键修改点
- 新增user非空判断,拉取用户失败时直接返回错误,不会触发null调用方法的报错
- 修正embeds参数格式,改为数组包裹单个Embed对象
- 调整fetch的第二个参数为true,强制走API拉取用户,避免缓存未命中导致的有效ID拉取失败问题
- 区分用户不存在和用户禁止DM两种错误场景,返回更准确的提示
- 交互回复统一用
interaction.reply,避免交互超时错误,可选加ephemeral: true让错误提示仅触发指令的用户可见
内容的提问来源于stack exchange,提问作者Koto
相关产品推荐
相关产品推荐

