From 679b56e525bb7667d2bc361c90985f1086f4201d Mon Sep 17 00:00:00 2001 From: Vini Date: Tue, 1 Sep 2026 20:34:42 -0300 Subject: [PATCH] fix(chatwoot): skip duplicate messages when device redelivers same key.id When a sender device redelivers a message with the same key.id (for example an unofficial client stuck in a resend loop), the live event path posted a new Chatwoot message on every arrival; one production report accumulated 837 copies of a single message. Reuse the dedup check that sendData already applies to media messages: query Chatwoot's messages.source_id through getExistingSourceIds before posting, gated by isImportHistoryAvailable, and skip the message when the WAID source id already exists in the target conversation. The helper is fail open: on lookup errors it logs and returns an empty set, so delivery is never blocked. The check sits at the top of the messages.upsert/send.message block so it covers text, reactions, interactive buttons, ads and media, and does not touch the messages.edit path, which legitimately re-posts using the original message's source id. Fixes #2675 --- .../chatbot/chatwoot/services/chatwoot.service.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/api/integrations/chatbot/chatwoot/services/chatwoot.service.ts b/src/api/integrations/chatbot/chatwoot/services/chatwoot.service.ts index c7a9753aa6..a00b42d11f 100644 --- a/src/api/integrations/chatbot/chatwoot/services/chatwoot.service.ts +++ b/src/api/integrations/chatbot/chatwoot/services/chatwoot.service.ts @@ -2240,6 +2240,17 @@ export class ChatwootService { return; } + if (body.key.id && this.isImportHistoryAvailable()) { + const sourceId = 'WAID:' + body.key.id; + const messageAlreadySaved = await chatwootImport.getExistingSourceIds([sourceId], getConversation); + if (messageAlreadySaved) { + if (messageAlreadySaved.size > 0) { + this.logger.warn('Message already saved on chatwoot'); + return; + } + } + } + const messageType = body.key.fromMe ? 'outgoing' : 'incoming'; if (isMedia) {