Skip to content

fix: use correct Prisma JSON path filter in getLastMessage#2515

Open
octo-patch wants to merge 1 commit intoEvolutionAPI:mainfrom
octo-patch:fix/issue-2495-archive-chat-json-filter
Open

fix: use correct Prisma JSON path filter in getLastMessage#2515
octo-patch wants to merge 1 commit intoEvolutionAPI:mainfrom
octo-patch:fix/issue-2495-archive-chat-json-filter

Conversation

@octo-patch
Copy link
Copy Markdown

@octo-patch octo-patch commented Apr 26, 2026

Fixes #2495

Problem

POST /chat/archiveChat/{instance} (and markChatUnread) always returns HTTP 500 with a PrismaClientValidationError when called with a chat string (no lastMessage provided).

The getLastMessage helper was building the Prisma where clause as:

{ key: { remoteJid: number }, instanceId: this.instance.id }

The key column is a Json/JsonB field. Prisma does not accept nested object syntax ({ remoteJid: value }) to filter inside a JSON column; it requires the explicit path form:

{ key: { path: ['remoteJid'], equals: value } }

Using the wrong form caused Prisma to throw PrismaClientValidationError: Unknown argument 'remoteJid'.

Solution

Changed the where clause in getLastMessage to use the correct Prisma JSON path filter:

const where: any = { key: { path: ['remoteJid'], equals: number }, instanceId: this.instanceId };

This matches the pattern already used elsewhere in the codebase (e.g. lines 5060-5061).

Testing

The fix aligns with the established Prisma JSON filtering pattern used throughout the file. archiveChat with {"chat": "<jid>", "archive": true} will now correctly resolve the last message instead of throwing a validation error.

Summary by Sourcery

Bug Fixes:

  • Correct JSON path filter in getLastMessage so chat archiving and unread-marking no longer fail with PrismaClientValidationError when only a chat JID is provided.

…lutionAPI#2495)

The `getLastMessage` function was using an invalid Prisma where-clause
syntax `{ key: { remoteJid: number } }` for a JSON/JSONB field. Prisma
requires `{ key: { path: ['remoteJid'], equals: value } }` to filter on
a JSON field path. This caused a PrismaClientValidationError whenever
`archiveChat` or `markChatUnread` called `getLastMessage` with a chat
number instead of providing lastMessage directly.

Co-Authored-By: Octopus <liyuan851277048@icloud.com>
@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented Apr 26, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Adjusts the Prisma JSON filter used in getLastMessage so that WhatsApp archive/unread operations correctly resolve the last message without throwing a PrismaClientValidationError.

Sequence diagram for getLastMessage using correct Prisma JSON path filter

sequenceDiagram
  participant Client
  participant ArchiveController
  participant BaileysStartupService
  participant PrismaRepository
  participant Database

  Client->>ArchiveController: POST /chat/archiveChat/{instance}
  ArchiveController->>BaileysStartupService: getLastMessage(number)
  BaileysStartupService->>BaileysStartupService: build where = { key: { path: ['remoteJid'], equals: number }, instanceId: this.instanceId }
  BaileysStartupService->>PrismaRepository: message.findMany(where)
  PrismaRepository->>Database: SELECT FROM message WHERE key->remoteJid = number AND instanceId = this.instanceId
  Database-->>PrismaRepository: messages
  PrismaRepository-->>BaileysStartupService: messages
  BaileysStartupService-->>ArchiveController: lastMessage
  ArchiveController-->>Client: 200 OK (chat archived)
Loading

Updated class diagram for BaileysStartupService getLastMessage query

classDiagram
  class BaileysStartupService {
    - prismaRepository PrismaRepository
    - instanceId string
    + getLastMessage(number string) Promise~Message[]~
  }

  class PrismaRepository {
    + message MessageDelegate
  }

  class MessageDelegate {
    + findMany(where any) Promise~Message[]~
  }

  class Message {
    + id string
    + key Json
    + instanceId string
    + content string
  }

  BaileysStartupService --> PrismaRepository : uses
  PrismaRepository --> MessageDelegate : exposes
  MessageDelegate --> Message : returns

  class GetLastMessageWhereFilter {
    + key JsonPathFilter
    + instanceId string
  }

  class JsonPathFilter {
    + path string[]
    + equals string
  }

  BaileysStartupService ..> GetLastMessageWhereFilter : builds
  GetLastMessageWhereFilter --> JsonPathFilter : contains
Loading

File-Level Changes

Change Details Files
Use Prisma JSON path-based filter instead of nested object syntax in getLastMessage and align instance identifier usage.
  • Replace invalid nested JSON filter { key: { remoteJid: number } } with Prisma-compliant JSON path filter { key: { path: ['remoteJid'], equals: number } } in getLastMessage.
  • Use this.instanceId instead of this.instance.id in the getLastMessage where-clause to match the rest of the service’s repository queries.
src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts

Assessment against linked issues

Issue Objective Addressed Explanation
#2495 Fix the PrismaClientValidationError in the archiveChat endpoint so that POST /chat/archiveChat/{instanceName} no longer throws an error related to an unknown remoteJid argument and successfully archives chats.
#2495 Ensure other endpoints using the same JID resolution / last-message lookup path (notably markChatUnread) no longer throw the same PrismaClientValidationError and function correctly.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

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 - I've left some high level feedback:

  • The change from instanceId: this.instance.id to instanceId: this.instanceId alters behavior beyond the Prisma JSON filter fix; please confirm this is intentional and consistent with how instanceId is handled in other methods of this service.
  • Instead of typing where as any, consider using the appropriate Prisma-generated type (e.g., Prisma.MessageWhereInput) so the compiler can help catch invalid JSON filter shapes in the future.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The change from `instanceId: this.instance.id` to `instanceId: this.instanceId` alters behavior beyond the Prisma JSON filter fix; please confirm this is intentional and consistent with how `instanceId` is handled in other methods of this service.
- Instead of typing `where` as `any`, consider using the appropriate Prisma-generated type (e.g., `Prisma.MessageWhereInput`) so the compiler can help catch invalid JSON filter shapes in the future.

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.

@octo-patch
Copy link
Copy Markdown
Author

Thanks for the review!

On the instanceId change: this.instanceId is a getter that returns this.instance.id (see channel.service.ts lines 99-100). They are semantically identical, but this.instanceId matches the established convention used everywhere else in whatsapp.baileys.service.ts and the rest of the codebase, so I changed it for consistency. No behavior change is intended.

On the Prisma.MessageWhereInput typing: I left where as any to keep the diff minimal and focused on the bug fix. The JSON path filter ({ key: { path: ['remoteJid'], equals: number } }) is correct at runtime but can be awkward to express through Prisma's generated types. Happy to follow up with proper typing in a separate PR if maintainers prefer.

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.

Bug: archiveChat fails with PrismaClientValidationError on v2.3.7

1 participant