Skip to content

createDiscordThread should recover existing thread on Discord 160004 error instead of silently failing #279

@spencerchubb

Description

@spencerchubb

Bug Description

When createDiscordThread receives a 160004 error from the Discord API ("A thread has already been created for this message"), both call sites catch the error, log it, and continue with discordThreadId left as undefined. This causes the bot to post a standalone message in the channel instead of replying in the existing thread.

Steps to Reproduce

  1. Set up a Discord adapter with a bot that responds to mentions
  2. Trigger a scenario where createDiscordThread is called for a message that already has a thread (e.g., duplicate webhook delivery, bot restart mid-processing, or a race condition between gateway and webhook handlers)
  3. The Discord API returns 400 with error code 160004: "A thread has already been created for this message"
  4. The bot posts its response as a standalone channel message instead of in the existing thread

Expected Behavior

When createDiscordThread gets a 160004 error, it should recover by using the existing thread's ID (which in Discord equals the parent message ID) and set discordThreadId accordingly. The bot should then reply in the existing thread.

Actual Behavior

The error is caught and logged, but discordThreadId remains undefined. The bot falls back to posting in the channel, producing a standalone message disconnected from the thread.

This happens at two call sites in packages/adapter-discord/src/index.ts:

  • Line ~640 (forwarded mention handler):

    catch (error) {
      this.logger.error("Failed to create Discord thread for mention", {
        error: String(error),
        messageId: data.id,
      });
      // discordThreadId remains undefined
    }
  • Line ~1955 (incoming mention handler):

    catch (error) {
      this.logger.error("Failed to create Discord thread for mention", {
        error: String(error),
        messageId: message.id,
      });
      // Continue without thread - will use channel
    }

Code Sample

Suggested fix for both catch blocks:


catch (error) {
  // Discord error 160004: thread already exists for this message
  // The thread ID equals the message ID in Discord
  if (String(error).includes("160004")) {
    discordThreadId = data.id; // or message.id at the other call site
    this.logger.debug("Thread already exists, using existing thread", {
      messageId: data.id,
      threadId: discordThreadId,
    });
  } else {
    this.logger.error("Failed to create Discord thread for mention", {
      error: String(error),
      messageId: data.id,
    });
  }
}

Chat SDK Version

4.20.2

Node.js Version

bun 1.2.15

Platform Adapter

Discord

Operating System

None

Additional Context

Error logs observed in production (Vercel):

[chat-sdk:discord] Discord API error {
  path: '/channels/foo/messages/bar/threads',
  method: 'POST',
  status: 400,
  error: '{"message": "A thread has already been created for this message", "code": 160004}'
}
[chat-sdk:discord] Failed to create Discord thread for mention {
  error: 'NetworkError: Discord API error: 400 {"message": "A thread has already been created for this message", "code": 160004}',
  messageId: 'foobar'
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions