Discord.js控制台发私信触发Cannot read property 'send' of undefined错误
报错核心原因
代码执行到dmper.send(...)时,dmper本身的值为undefined,空对象不存在send方法,因此触发了类型错误。
为什么会出现dmper为undefined
- 代码中使用
client.users.cache.get("704996899132014652")获取用户对象,这个方法只会从bot运行时的本地内存缓存里查找对应ID的用户。Discord.js 默认不会缓存全平台所有用户的信息,仅会缓存和bot存在直接交互的用户(比如同处一个服务器、主动给bot发过消息、被bot加载过成员列表的用户)。如果目标用户从未和bot产生过交集,本地缓存里根本没有对应的条目,方法就会返回空值。 - 就算目标用户和bot在同一个服务器,如果bot初始化时没有开启
GuildMembers网关意图,Discord.js 不会自动拉取服务器的全量成员列表到缓存中,同样会出现缓存缺失的问题。
修复步骤
- 替换本地缓存获取用户的逻辑,改为通过Discord官方API拉取目标用户对象。因为API请求是异步操作,需要把原来的监听回调改成async异步函数,配合
await等待请求完成后再执行后续操作。 - 增加空值校验,获取到用户对象后先判断是否存在,避免后续空值调用方法触发报错。
- 核对输入的目标用户ID是否准确,排查是否存在漏写、多输数字的问题。
修复后的参考实现
let y = process.openStdin() y.addListener('data', async res => { let x = res.toString().trim().split(/ +/g) // 用fetch替代cache.get,优先查本地缓存,缓存缺失时自动从Discord服务端拉取用户对象,不依赖前置缓存存在 const dmper = await client.users.fetch("704996899132014652"); // 空值校验 if (!dmper) return console.log("未查询到对应ID的用户,取消发送"); await dmper.send(x.join(' ')); })
避坑提示
- 必须在Discord开发者后台为当前bot开启用户读取、消息发送的相关权限与网关意图,否则API请求会被平台拒绝,依然无法获取到用户对象。
- 如果目标用户开启了“仅接收好友私信”的隐私设置,即使成功获取到用户对象,
send请求也会被平台拦截,需要单独捕获发送环节的异常,避免主程序崩溃。
内容的提问来源于stack exchange,提问作者yas
相关产品推荐
相关产品推荐

