求助升级Discord机器人至Discord.js v12的TypeError报错修复
Discord.js v12 报错
TypeError: client.channels.fetch(...).send is not a function 修复方案 报错核心原因
Discord.js v12 中所有 fetch() 类方法均为异步方法,返回 Promise 而非直接返回目标对象。
原代码直接对 client.channels.fetch(logsChannel) 链式调用 .send(),本质是给 Promise 对象调用了不存在的 send 方法,因此触发报错。
另外还有几处 v12 适配遗漏的问题会导致后续运行异常,一并修复。
具体修复项
- 所有异步
fetch操作必须用await等待 Promise 解析,拿到有效的频道实例后再调用send方法 - 事件回调中用到
await的,必须声明为async异步函数 - v12 中用户、服务器的头像 URL 是方法而非属性,必须加括号调用:
avatarURL()、iconURL(),不能直接当属性读取 - 补充错误捕获,防止日志频道 ID 无效、未缓存等情况导致机器人崩溃
- 简化原有空集合判断逻辑,直接用 Discord.js Collection 自带的
size属性判断,避免冗余循环
完整适配后的可运行代码
const Discord = require('discord.js'); // 补充 partials 配置,支持接收未缓存的消息事件,避免空值报错 const client = new Discord.Client({ partials: ['MESSAGE', 'CHANNEL'] }); const { prefix, token, logsChannel } = require('./config.json'); client.once('ready', () => { console.log('I am alive!'); }); // 简化后的空集合判断函数 function isEmpty(collection) { return collection.size === 0; } // 消息发送日志模块 client.on('message', async message => { if(message.author.bot) return; const username = message.author.tag; const channel = message.channel.name; const serverAvatarURL = message.guild.iconURL(); const attachment = message.attachments.array(); const img = isEmpty(attachment) ? "" : attachment[0].url; const embed_send = new Discord.MessageEmbed() .setAuthor(username, message.author.avatarURL()) .setColor('23c115') .setTitle("Message sent!") .setDescription(message.content + " " + img) .setImage(img) .setFooter("#" + channel) .setTimestamp(); // 修复核心报错:await 等待 fetch 拿到频道实例,补充错误捕获 try { const logChannel = await client.channels.fetch(logsChannel); await logChannel.send(embed_send); } catch (err) { console.error('日志频道发送失败:', err); } }); // 消息编辑日志模块 client.on("messageUpdate", async(oldMessage, newMessage) => { // 兼容未缓存消息的空值场景 if(!oldMessage.content || !newMessage.content) return; if (oldMessage.content === newMessage.content) return; const attachment = oldMessage.attachments.array(); const img = isEmpty(attachment) ? "" : attachment[0].url; const embed_edit = new Discord.MessageEmbed() .setAuthor(oldMessage.author.tag, oldMessage.author.avatarURL()) .setColor('2615c1') .setTitle("Message edited!") .addField("Old", oldMessage.content + " " + img, true) .addField("New", newMessage.content + " " + img, true) .setFooter("#" + oldMessage.channel.name) .setTimestamp(); try { const logChannel = await client.channels.fetch(logsChannel); await logChannel.send(embed_edit); } catch (err) { console.error('日志频道发送失败:', err); } }); // 消息删除日志模块 client.on("messageDelete", async message => { const attachment = message.attachments.array(); const img = isEmpty(attachment) ? "" : attachment[0].url; const embed_delete = new Discord.MessageEmbed() .setAuthor(message.author.tag, message.author.avatarURL()) .setColor('c11515') .setTitle("Message deleted!") .setDescription(message.content + " " + img) .setImage(img) .setFooter("#" + message.channel.name) .setTimestamp(); try { const logChannel = await client.channels.fetch(logsChannel); await logChannel.send(embed_delete); } catch (err) { console.error('日志频道发送失败:', err); } }); client.login(token);
注意事项
请确保
config.json中的logsChannel是合法的频道 ID 字符串,且机器人对该日志频道拥有「发送消息」「嵌入链接」权限。
若机器人仍无法正常接收消息事件,可在 Client 初始化时补充intents配置,显式开启消息读取、频道读取权限。
内容的提问来源于stack exchange,提问作者Random
相关产品推荐
相关产品推荐

