fix: Erro ao enviar mensagem para grupos (remoteJid failed constraint) by moothz · Pull Request #2162 · EvolutionAPI/evolution-api · GitHub
Skip to content

fix: Erro ao enviar mensagem para grupos (remoteJid failed constraint)#2162

Merged
DavidsonGomes merged 3 commits intoEvolutionAPI:developfrom
moothz:fix/saveOnWhatsappCache-remoteJid-failed-constraint
Nov 7, 2025
Merged

fix: Erro ao enviar mensagem para grupos (remoteJid failed constraint)#2162
DavidsonGomes merged 3 commits intoEvolutionAPI:developfrom
moothz:fix/saveOnWhatsappCache-remoteJid-failed-constraint

Conversation

@moothz
Copy link
Copy Markdown
Contributor

@moothz moothz commented Oct 30, 2025

📋 Description

O objetivo principal destas modificações é corrigir o problema das mensagens não serem enviadas para alguns grupos, principalmente os que tem o número do criador no jid (ex.: '559911223345-1234567890@g.us').

A interrupção no fluxo do request é causada por um erro ao tentar criar um novo registro na base de dados com um remoteJid já existente, isto acontece pois os registros são buscados utilizando apenas o jidOptions, que às vezes não tem o atual remoteJid na lista.

O erro em questão:

Invalid `prismaRepository.isOnWhatsapp.create()` invocation in
evolution-api/src/utils/onWhatsappCache.ts:130:45
n
  127     },
  128   });
  129 } else {
 130   await prismaRepository.isOnWhatsapp.create(
Unique constraint failed on the fields: (`remoteJid`)

Os dados diretamente na base de dados, mostrando que o remoteJid não estava no jidOptions:

SELECT * FROM "IsOnWhatsapp" WHERE "remoteJid" = '554212345678-1625864928@g.us';
            id             |          remoteJid           |                        jidOptions                         |        createdAt        |       updatedAt        | lid
---------------------------+------------------------------+-----------------------------------------------------------+-------------------------+------------------------+-----
 cm...ok525sz | 554212345678-1625864928@g.us | 5542998558888-1625864928@g.us,55428558888-1625864928@g.us | 2025-10-19 13:40:08.508 | 2025-10-21 15:49:53.21 |

A lógica de busca foi alterada para prevenir erros de 'Unique constraint failed'.
Para corrigir isso, a busca no banco agora usa OR para verificar tanto pelo jidOptions quanto pelo remoteJid em uma única query.

Além dessa correção, outras otimizações foram implementadas:

  1. Updates Desnecessários: A função agora compara os dados novos com os dados do 'existingRecord'. O update só é executado se houver de fato uma mudança, reduzindo escritas desnecessárias no banco.
  2. Processamento Paralelo: A iteração sequencial (for...of) foi substituída por Promise.allSettled, permitindo que todos os itens do array data sejam processados em paralelo.
  3. Consistência de Dados: Os JIDs em jidOptions agora são ordenados antes de serem salvos ou comparados. Isso garante que a verificação de "mudança" seja precisa, independentemente da ordem de inserção.
  4. Refactor: A lógica de unificação de JIDs foi simplificada para usar Set e um helper normalizeJid foi criado para limpar o código. O código foi envolto em um try-catch para evitar interrupção do fluxo de envio de mensagens, visto que o cache não é crítico.

🧪 Type of Change

  • 🐛 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • 📚 Documentation update
  • 🔧 Refactoring (no functional changes)
  • ⚡ Performance improvement
  • 🧹 Code cleanup
  • 🔒 Security fix

🧪 Testing

  • Manual testing completed
  • Functionality verified in development environment
  • No breaking changes introduced
  • Tested with different connection types (if applicable)

✅ Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have manually tested my changes thoroughly
  • I have verified the changes work with different scenarios
  • Any dependent changes have been merged and published

📝 Additional Notes

TODO: Investigar a causa raiz de o remoteJid às vezes não estar no jidOptions no momento da busca inicial. Também notei na base de dados que alguns números estão vindo com o "@g.us" duplicado.

Summary by Sourcery

Fix cache save errors for WhatsApp group messages and optimize saveOnWhatsappCache

Bug Fixes:

  • Prevent unique constraint failure by querying cache entries against both jidOptions and remoteJid

Enhancements:

  • Normalize and sort JIDs to ensure consistent cache entries
  • Process cache updates in parallel using Promise.allSettled
  • Compare new and existing records to skip unnecessary database writes

Chores:

  • Extract normalizeJid helper and encapsulate processing in try-catch for resilience
  • Exit early when caching is disabled via configuration

…B writes

Refactors the cache-saving logic to prevent `Unique constraint failed` errors. This issue occurs when an item's `remoteJid` is not yet included in the `jidOptions` of the existing record.

The database query now uses an `OR` condition to find a matching record by either `jidOptions` (using `contains`) or by the `remoteJid` itself in a single query.

Additionally, this commit introduces several performance optimizations:

1.  **Skip Unnecessary Updates**: The function now performs a deep comparison between the new payload and the `existingRecord`. An `update` operation is only executed if the data has actually changed, reducing unnecessary database writes.
2.  **Parallel Processing**: The sequential `for...of` loop has been replaced with `Promise.allSettled`. This allows all items in the `data` array to be processed concurrently, significantly speeding up execution for batch inputs.
3.  **Data Consistency**: The JIDs in `jidOptions` are now sorted alphabetically before being joined into a string. This ensures that the change-detection logic is accurate, regardless of the order in which JIDs were discovered.
4.  **Refactor**: Simplified JID unification logic using a `Set` and introduced a `normalizeJid` helper function for cleaner code.

TODO: Investigate the root cause of why `remoteJid` is sometimes not present in `jidOptions` upon initial discovery.
@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented Oct 30, 2025

@moothz moothz changed the title fix: Erro enviar mensagem para grupos (remoteJid failed constraint) fix: Erro ao enviar mensagem para grupos (remoteJid failed constraint) Oct 30, 2025
Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes - here's some feedback:

  • Consider limiting the concurrency in Promise.allSettled (e.g. via a p-limit or batching) for large data arrays to prevent overwhelming your database connections.
  • Using Prisma’s contains on the comma-separated jidOptions string may produce false positives; for more reliable lookups consider storing jidOptions as an array field or using an exact-match filter.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Consider limiting the concurrency in Promise.allSettled (e.g. via a p-limit or batching) for large data arrays to prevent overwhelming your database connections.
- Using Prisma’s contains on the comma-separated jidOptions string may produce false positives; for more reliable lookups consider storing jidOptions as an array field or using an exact-match filter.

## Individual Comments

### Comment 1
<location> `src/utils/onWhatsappCache.ts:99-108` </location>
<code_context>
+      // 2. Unifica todos os JIDs usando um Set para garantir valores únicos
+      const finalJidOptions = new Set(expandedJids);

-      if (existingRecord?.jidOptions) {
-        const existingJids = existingRecord.jidOptions.split(',');
-        // TODO: Adicionar JIDs existentes que não estão na lista atual
-        existingJids.forEach((jid) => {
-          if (!finalJidOptions.includes(jid)) {
-            finalJidOptions.push(jid);
-          }
-        });
+      if (lidAltJid) {
+        finalJidOptions.add(lidAltJid);
       }
-
-      // TODO: Se tiver remoteJidAlt com @lid novo, adicionar
-      if (altJid && !finalJidOptions.includes(altJid)) {
-        finalJidOptions.push(altJid);
+      
+      if (existingRecord?.jidOptions) {
+        existingRecord.jidOptions.split(',').forEach(jid => finalJidOptions.add(jid));
       }

</code_context>

<issue_to_address>
**suggestion (bug_risk):** Merging existing JIDs may introduce legacy or malformed entries.

Validate each JID's format before adding to finalJidOptions to prevent legacy or malformed entries from being included.

Suggested implementation:

```typescript
      // 2. Unifica todos os JIDs usando um Set para garantir valores únicos e válidos
      function isValidJid(jid: string | null | undefined): boolean {
        // Exemplo de validação: JID deve conter '@' e não ser vazio
        return typeof jid === 'string' && jid.includes('@') && jid.trim().length > 0;
      }

      const finalJidOptions = new Set(
        expandedJids.filter(jid => isValidJid(jid))
      );

```

```typescript
      if (lidAltJid && isValidJid(lidAltJid)) {
        finalJidOptions.add(lidAltJid);
      }

```

```typescript
      if (existingRecord?.jidOptions) {
        existingRecord.jidOptions
          .split(',')
          .filter(jid => isValidJid(jid))
          .forEach(jid => finalJidOptions.add(jid));
      }

```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

moothz and others added 2 commits October 30, 2025 16:18
Descartei as mudanças nos arquivos que não me pertencem, dá uma folga aí, botinho
@DavidsonGomes DavidsonGomes merged commit 27be03e into EvolutionAPI:develop Nov 7, 2025
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants