Title: Discord API returns 403 'internal network error' (Code 40333) when bot adds reaction via Google Apps Script

159 views
Skip to first unread message

Kenneth Roger Gavino

unread,
Jun 28, 2025, 5:38:07 AMJun 28
to Google Apps Script Community



I am developing a Discord bot using Google Apps Script. The bot's primary function is to post an approval message as a reply in a channel and then immediately add a '👍' reaction to its own message.

While the message posting works perfectly, the subsequent API call to add the reaction fails with a very specific error:

*   **HTTP Response Code:** `403`
*   **Response Body:** `{"message": "internal network error", "code": 40333}`

This is confusing because my bot has the **Administrator** role in the Discord server, which should grant it all necessary permissions.

#### **The Workflow**

1.  A user triggers an action in a Google Sheets-backed web app.
2.  The `processApproval` function is called in Google Apps Script.
3.  `sendBotReply` successfully posts a message to the correct channel via the Discord API. It returns the new message's link/ID.
4.  `addDiscordReaction` is called immediately with the new message's details. **This is the step that fails.**

#### **Relevant Code (Google Apps Script)**

Here is the simplified code for the core logic. The `sendBotReply` function is included to show that `UrlFetchApp` and the Bot Token are working correctly for posting messages.

```javascript
const BOT_TOKEN = '...'; // My bot token is valid and works for posting.

/**
 * Main orchestrator function.
 */
function processApproval() {
  try {
    // This part works: The bot posts the message and I get a valid link.
    const messageLinkFromBot = sendBotReply();

    // This is the call that fails.
    addDiscordReaction(messageLinkFromBot);

  } catch (error) {
    Logger.log('Error in processApproval: ' + error.toString());
  }
}


/**
 * Sends a message as the bot. THIS FUNCTION WORKS.
 * Returns the URL of the newly created message.
 */
function sendBotReply() {
    const channelId = '123456789012345678'; // Example Channel ID
    const apiUrl = `https://discord.com/api/v10/channels/${channelId}/messages`;

    const payload = {
        content: `This is a test message from the bot.`
    };

    const options = {
        method: 'post',
        contentType: 'application/json',
        headers: {
          'Authorization': 'Bot ' + BOT_TOKEN
        },
        payload: JSON.stringify(payload),
        muteHttpExceptions: true
    };

    const response = UrlFetchApp.fetch(apiUrl, options);
    const responseData = JSON.parse(response.getContentText());
   
    // Example return: "https://discord.com/channels/SERVER_ID/CHANNEL_ID/MESSAGE_ID"
    return `https://discord.com/channels/${responseData.guild_id}/${responseData.channel_id}/${responseData.id}`;
}


/**
 * Tries to add a reaction to a message. THIS FUNCTION FAILS.
 */
function addDiscordReaction(messageLink) {
  // Assume parseDiscordLink correctly extracts IDs from the messageLink
  const ids = parseDiscordLink(messageLink);
  // ids = { channelId: '...', messageId: '...' }

  if (!ids) {
      throw new Error(`Could not parse IDs from message link for reaction: ${messageLink}`);
  }
 
  const reactionEmoji = encodeURIComponent('👍'); // Thumbs Up
  const url = `https://discord.com/api/v10/channels/${ids.channelId}/messages/${ids.messageId}/reactions/${reactionEmoji}/@me`;
 
  const options = {
    method: 'put',
    headers: {
      'Authorization': 'Bot ' + BOT_TOKEN
    },
    muteHttpExceptions: true
  };

  const response = UrlFetchApp.fetch(url, options);
  const responseCode = response.getResponseCode();
  const responseBody = response.getContentText();

  // THE PROBLEM IS HERE:
  // responseCode is 403
  // responseBody is {"message": "internal network error", "code": 40333}
 
  if (responseCode !== 204) {
    Logger.log(`Failed to add reaction. Code: ${responseCode}, Body: ${responseBody}`);
    throw new Error(`Failed to add reaction. API responded with code ${responseCode}.`);
  }
  Logger.log(`Successfully added reaction to message ${ids.messageId}`);
}

// Helper function to extract IDs
function parseDiscordLink(link) {
    if (!link) return null;
    const match = link.match(/channels\/\d+\/(\d+)\/(\d+)/);
    if (match && match.length === 3) {
        return { channelId: match[1], messageId: match[2] };
    }
    return null;
}
```

#### **What I've Checked**

1.  **Permissions:** The bot has the **Administrator** role. This includes `Add Reactions` and `Read Message History`.
2.  **Bot Token:** The token is correct and has the necessary scopes (`bot`, `applications.commands`). It works perfectly for the `sendBotReply` function.
3.  **API Endpoint:** The URL `.../reactions/{emoji}/@me` with the `PUT` method is correct according to the [Discord API documentation](https://discord.com/developers/docs/resources/channel#create-reaction).
4.  **IDs and Emoji:** The `channelId`, `messageId`, and URL-encoded `emoji` are all correct. I have logged them and they are valid.
5.  **Timing:** I tried adding a `Utilities.sleep(2000)` between posting and reacting, but it made no difference.
6.  **Error Code:** The error is not the typical `50013: Missing Permissions` error. The `40333: internal network error` seems to indicate something else is wrong.

#### **The Question**

What could be causing this specific `40333: internal network error` when trying to add a reaction? Given that the bot has full Administrator permissions and can successfully post the message it's trying to react to, what could be the root cause? Is this a known issue with Google Apps Script's `UrlFetchApp` or a more obscure Discord API behavior?
Reply all
Reply to author
Forward
0 new messages