如何修复Discord机器人重启后消息反应检测失效问题
Hey there! I get it—frustrating when your bot works perfectly until a restart, then stops picking up reactions on older messages. Let's break down why this happens and how to fix it.
Why This Happens
By default, Discord.js doesn't cache messages sent before your bot boots up. When a user reacts to one of those pre-restart messages, the messageReactionAdd event never fires because the bot doesn't have that message stored in its memory.
The Solution: Use Partials
To fix this, we need to enable Partials in your bot configuration. Partials let the bot receive events for objects that aren't fully cached (like old messages/reactions) and fetch the full data when needed.
Step 1: Update Bot Initialization
First, enable Partials for Message, Reaction, and User when creating your client. Don't forget to include the necessary intents—make sure you have the ones required for messages and reactions.
const { Client, Partials } = require('discord.js'); const prefix = '!'; // Replace with your actual prefix const bot = new Client({ intents: [ // Add the intents your bot needs 'Guilds', 'GuildMessages', 'DirectMessages', 'MessageReactions', 'MessageContent' // Required to read message content (enable in Discord Developer Portal too!) ], partials: [Partials.Message, Partials.Reaction, Partials.User] });
Step 2: Modify the messageReactionAdd Event
Update your reaction event handler to check if the reaction is a partial, and fetch the full data if needed. This ensures we can access the message content even for pre-restart messages.
bot.on("messageReactionAdd", async (messageReaction, user) => { // Skip bot reactions to avoid loops if (user.bot) return; // Fetch full reaction data if it's a partial if (messageReaction.partial) { try { await messageReaction.fetch(); } catch (err) { console.error("Failed to fetch partial reaction:", err); return; } } // Check if the message matches your target content if (messageReaction.message.content === "Message") { await messageReaction.message.reply("It works."); } });
Step 3: Keep Your Test Command (Adjust if Needed)
Your existing test command should still work, but just make sure your intents include DirectMessages to handle DM interactions:
bot.on("message", async (message) => { if (message.content.startsWith(prefix + "test")) { await message.delete(); const dmChannel = await message.member.createDM(); const sentMessage = await dmChannel.send("Message"); await sentMessage.react("✅"); } });
Important Notes
- Don't forget to enable the Message Content Intent in your Discord Developer Portal under your bot's "Privileged Gateway Intents" section—this is required to read message content in newer Discord.js versions.
- Always use
async/awaitwhen dealing with Discord API calls (like fetching reactions or sending messages) to avoid race conditions.
内容的提问来源于stack exchange,提问作者Antonin_04

