You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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构建失败。结合代码来看:

  1. 参数检查时机错误:在API请求回调内才检查是否输入地点,会导致无效请求且可能触发后续逻辑异常。
  2. 未校验API返回的current/location字段完整性:若部分地点的API返回缺失关键字段,访问current.imageUrl等属性会导致Embed构建失败。
  3. 未捕获发送消息时的异常:即使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("无法发送天气信息,请稍后重试");
            }
        });
    }
};

修改说明

  1. 提前参数校验:在发起API请求前检查是否输入地点,减少无效请求。
  2. 增强数据校验:确保current和location字段存在,避免访问undefined属性。
  3. 容错处理缩略图:仅当API返回有效图片URL时才设置缩略图,防止破坏Embed结构。
  4. 异常捕获:添加try-catch捕获消息发送时的异常,避免机器人因单个请求崩溃。
  5. 优化错误提示:将原始API错误转换为用户友好的提示,同时保留日志便于排查。

内容的提问来源于stack exchange,提问作者FireFenrir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 03:15:40