Discord Bot Stops Working Due to Promise Rejection Error

I’m building a Discord bot that needs to send direct messages to all members in a server. The problem is when the bot can’t deliver a message to someone (maybe they blocked DMs or left the server), it throws a promise rejection error and completely stops working.

I need the bot to keep going even when it hits these errors. Right now it just crashes and won’t send any more messages.

Here’s what I have so far:

client.on('messageCreate', msg => {
  if (msg.content.startsWith('!broadcast')) {
    try {
      msg.guild.members.forEach(user =>
        user.send("Hello everyone!"))
    }
    catch(err) {
      console.log('Failed to send message!');
    }
  }
})

How can I make this work properly without the bot dying when it encounters delivery failures?

You’re getting unhandled promise rejections because user.send() returns a promise, but forEach doesn’t wait for async operations. Your try-catch block can’t catch these rejections.

I’ve hit this same issue building a notification bot. Switch to Promise.allSettled() instead of forEach - it handles all promises whether they succeed or fail:

client.on('messageCreate', async msg => {
  if (msg.content.startsWith('!broadcast')) {
    const promises = msg.guild.members.cache.map(member => 
      member.send("Hello everyone!").catch(err => null)
    );
    await Promise.allSettled(promises);
  }
})

This keeps your bot running even when some DMs fail.

your forEach ain’t handling async right. You should either wrap it in an async function and use await user.send().catch(err => console.log('dm failed')) or just add .catch() to each send call to avoid crashing the bot.

Had the same crash with my moderation bot last month. The problem is forEach fires all send operations at once without throttling - Discord’s API hates that. You’ll hit rate limits fast.

I fixed it by adding delays between messages and handling rejections properly. Process members one by one with a timeout instead of blasting everything at once:

client.on('messageCreate', async msg => {
  if (msg.content.startsWith('!broadcast')) {
    for (const member of msg.guild.members.cache.values()) {
      try {
        await member.send("Hello everyone!");
        await new Promise(resolve => setTimeout(resolve, 1000));
      } catch (error) {
        console.log(`Failed to DM ${member.user.tag}`);
      }
    }
  }
})

Keeps your bot stable and respects Discord’s rate limits.