Discord.js v13天气机器人报Cannot send an empty message错误求助
天气机器人触发DiscordAPIError: Cannot send an empty message错误
几个月前已解决过相同问题,未修改代码的天气机器人昨日起再次出现异常:部分地点查询正常,其余地点执行命令后延迟报错,错误信息如下:
/home/container/node_modules/discord.js/src/rest/RequestHandler.js:350 throw new DiscordAPIError(data, res.status, request); ^ DiscordAPIError: Cannot send an empty message at RequestHandler.execute (/home/container/node_modules/discord.js/src/rest/RequestHandler.js:350:13) at processTicksAndRejections (node:internal/process/task_queues:96:5) at async RequestHandler.push (/home/container/node_modules/discord.js/src/rest/RequestHandler.js:51:14) at async TextChannel.send (/home/container/node_modules/discord.js/src/structures/interfaces/TextBasedChannel.js:175:15) { method: 'post', path: '/channels/959726696393748519/messages', code: 50006, httpStatus: 400, requestData: { json: { content: undefined, tts: false, nonce: undefined, embeds: undefined, components: undefined, username: undefined, avatar_url: undefined, allowed_mentions: undefined, flags: undefined, message_reference: undefined, attachments: undefined, sticker_ids: undefined }, files: [] } }
完整代码
index.js
const Discord = require("discord.js"); var weather = require('weather-js'); const { Client, GuildMember, Message } = require("discord.js"); const config = require("./config.json") const client = new Client({ intents: ["GUILD_MESSAGES", "GUILD_MEMBERS", "GUILDS"] }); const fs = require('fs'); client.commands = new Discord.Collection(); const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js')); for (const file of commandFiles) { const command = require(`./commands/${file}`); client.commands.set(command.name, command); } const prefix = "!"; client.on("ready", () => { ... client.on('messageCreate', async message => { if (!message.content.startsWith(prefix)) return; let args = message.content.slice(prefix.length).split(" "); let command = args.shift().toLowerCase() if (command === "weather") { client.commands.get("weather").execute(message, args, Discord, weather) } }); client.login(config.token);
weather.js
var weather = require('weather-js'); const Discord = require('discord.js'); module.exports = { name: 'weather', description: "Used to get the weather of a place", execute(message, args, Discord, weather) { const city = args[0] weather.find({search: args.join(" "), degreeType: "C"}, function(error, result){ if (error) return message.channel.send(error) if (!city) return message.channel.send("You must specify a location please!") if (result === undefined || result.length === 0) return message.channel.send("**Invalid location**") let current = result[0].current let location = result[0].location const embed = new Discord.MessageEmbed() .setTitle(`Weather forecast for ${current.observationpoint || "NO DATA"}`) .setDescription(`${current.skytext || "NO DATA"}`) //Using a direct call can cause an error. .setThumbnail(current.imageUrl) //If this part is the culprit let me know .setColor("RANDOM") .setTimestamp() .addField("Temperature: ", `${current.temperature || "NO DATA"} °C`, true) .addField("Wind Speed: ", `${current.winddisplay || "NO DATA"}`, true) .addField("Humidity: ", `${current.humidity || "NO DATA"}%`, true) .addField("Timezone: ", `UTC${location.timezone || "NO DATA"}`, true) message.channel.send({ embeds: [embed]}); }) } }
已尝试查阅相关资料、重写weather-js相关代码,均未解决问题,寻求帮助。
问题分析与解决方案
核心问题
错误提示Cannot send an empty message说明发送消息时embeds字段为undefined,本质是天气API返回数据异常或代码未处理缺失字段,导致Embed构建失败。结合代码来看:
- 参数检查时机错误:在API请求回调内才检查是否输入地点,会导致无效请求且可能触发后续逻辑异常。
- 未校验API返回的
current/location字段完整性:若部分地点的API返回缺失关键字段,访问current.imageUrl等属性会导致Embed构建失败。 - 未捕获发送消息时的异常:即使Embed构建有问题,也没有容错处理。
修改后的weather.js代码
var weather = require('weather-js'); const Discord = require('discord.js'); module.exports = { name: 'weather', description: "Used to get the weather of a place", execute(message, args, Discord, weather) { // 提前检查地点参数,避免无效API请求 if (!args[0]) return message.channel.send("You must specify a location please!"); weather.find({search: args.join(" "), degreeType: "C"}, function(error, result){ // 处理API错误,避免直接抛出原始错误 if (error) { console.error(error); return message.channel.send(`获取天气数据失败:${error.message || "未知错误"}`); } // 校验返回结果有效性 if (!result || result.length === 0) return message.channel.send("**Invalid location**"); const current = result[0].current; const location = result[0].location; // 确保核心数据存在,避免访问undefined属性 if (!current || !location) return message.channel.send("无法获取该地点的天气数据"); const embed = new Discord.MessageEmbed() .setTitle(`Weather forecast for ${current.observationpoint || "NO DATA"}`) .setDescription(`${current.skytext || "NO DATA"}`) .setColor("RANDOM") .setTimestamp(); // 仅当缩略图URL存在时才设置,防止传入undefined破坏Embed结构 if (current.imageUrl) { embed.setThumbnail(current.imageUrl); } // 添加字段,确保所有字段都有默认值 embed.addField("Temperature: ", `${current.temperature || "NO DATA"} °C`, true) .addField("Wind Speed: ", `${current.winddisplay || "NO DATA"}`, true) .addField("Humidity: ", `${current.humidity || "NO DATA"}%`, true) .addField("Timezone: ", `UTC${location.timezone || "NO DATA"}`, true); // 捕获发送消息时的异常,避免机器人崩溃 try { message.channel.send({ embeds: [embed]}); } catch (sendError) { console.error("发送天气消息失败:", sendError); message.channel.send("无法发送天气信息,请稍后重试"); } }); } };
修改说明
- 提前参数校验:在发起API请求前检查是否输入地点,减少无效请求。
- 增强数据校验:确保
current和location字段存在,避免访问undefined属性。 - 容错处理缩略图:仅当API返回有效图片URL时才设置缩略图,防止破坏Embed结构。
- 异常捕获:添加try-catch捕获消息发送时的异常,避免机器人因单个请求崩溃。
- 优化错误提示:将原始API错误转换为用户友好的提示,同时保留日志便于排查。
内容的提问来源于stack exchange,提问作者FireFenrir
相关产品推荐
相关产品推荐

