Discord.js 12.5.3 messageUpdate报null的id属性读取TypeError
错误产生原因
报错指向newMessage.author.id读取失败,核心原因是newMessage.author值为null:
- Discord.js的
messageUpdate事件触发时,若对应消息未被机器人本地缓存、是系统内置消息、仅嵌入/反应等附属内容更新而非正文更新,传递给回调的oldMessage、newMessage可能是不完整的Partial(部分)结构,author、content等属性不会被填充,直接读取就会触发空指针错误。 - 现有代码仅校验了频道类型、新旧消息正文是否一致,没有对Partial消息、空属性做前置拦截。机器人刚启动时缓存内的消息都是完整结构,因此前几分钟可以正常运行,等遇到非缓存类的消息更新事件时就会触发报错,进程以状态码1异常退出。
修复方案
需要在业务逻辑前增加前置校验,从根源避免空值读取:
- 先判断消息是否为Partial结构,若为Partial则拉取完整消息数据,或直接跳过本次事件处理
- 提前校验
author、content、guild等核心属性是否存在,拦截属性缺失的异常事件 - 补充对机器人自身消息的过滤,避免记录机器人自己的消息编辑产生冗余日志
修复后的可运行代码如下:
c.on("messageUpdate", async function(oldMessage, newMessage) { // 拦截非文本频道消息,用可选链避免channel为空时报错 if (oldMessage.channel?.type !== "text" || newMessage.channel?.type !== "text") return; // 拉取Partial类型消息的完整结构 if (oldMessage.partial) oldMessage = await oldMessage.fetch(); if (newMessage.partial) newMessage = await newMessage.fetch(); // 核心属性空值校验 if (!newMessage.author || !oldMessage.content || !newMessage.content) return; // 过滤机器人发送的消息 if (newMessage.author.bot) return; // 正文无变化则不记录日志 if (oldMessage.content === newMessage.content) return; send_log( c, oldMessage.guild, "YELLOW", "Message UPDATED", ` **Author : ** <@${newMessage.author.id}> **Date : ** <t:${parseInt(newMessage.createdTimestamp / 1000)}:R> **Channel : ** <#${newMessage.channel.id}> **Orignal Message : ** \`\`\` ${oldMessage.content.replace(/`/g, "'")} \`\`\` **Updated Message : ** \`\`\` ${newMessage.content.replace(/`/g, "'")} \`\`\`` ); });
注意:如果你使用的是v14及以上版本的Discord.js,文本频道的类型枚举值从
text改为GuildText,需要对应调整频道类型判断逻辑,否则会出现所有文本频道消息都被拦截的问题。
内容的提问来源于stack exchange,提问作者Kobayashi Kenji
相关产品推荐
相关产品推荐

