makeplane / makeplane/plane

notifications: bulk_create missing ignore_conflicts causes duplicate in-app notifications on Celery task retry

Open Beginner friendly
#9,600 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
59.6k
Forks
5.8k
Avg merge
1d 22h
Merged PRs (30d)
49

Description

Bug Description

Notification.objects.bulk_create in the
otifications Celery task is missing ignore_conflicts=True. If the task is dispatched twice for the same event (worker restart, Celery retry, duplicate .delay() call upstream), every subscriber receives duplicate in-app notification entries that are permanently visible in their inbox.

The omission stands out because the very next line, EmailNotificationLog.objects.bulk_create, already uses ignore_conflicts=True.

Affected file

pps/api/plane/bgtasks/notification_task.py, lines 669-670:

`python
Notification.objects.bulk_create(bulk_notifications, batch_size=100)

vs. the line immediately after:

EmailNotificationLog.objects.bulk_create(bulk_email_logs, batch_size=100, ignore_conflicts=True)
`

Failure scenario

  1. A Celery worker processes the
    otifications task and crashes after ulk_create (before ACK).
  2. The broker re-queues the task. The second worker runs the same task for the same event.
  3. Notification.objects.bulk_create succeeds again (no unique constraint to block it).
  4. Every workspace member who was notified now has two identical entries in their notification feed. These are permanent - there is no deduplication on read.

This also occurs when two Celery Beat instances run (multi-pod deployments) and both schedule the same notification.

Fix

python Notification.objects.bulk_create(bulk_notifications, batch_size=100, ignore_conflicts=True)

A unique constraint on (receiver_id, actor_id, entity_identifier, entity_type) would make the fix robust, but ignore_conflicts=True is the minimal safe change matching the existing email log pattern.

Environment

Plane develop branch (2026-08-13).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in apps/api/plane/bgtasks/notification_task.py around lines 669-670 and compare Notification.objects.bulk_create with the following EmailNotificationLog.objects.bulk_create call. Trace the notification task's retry or duplicate-dispatch path, then verify that processing the same event again does not create duplicate in-app notification entries.

Written by the indexing model from the issue text.

Assessment

Tech stack
django, python
Domain
backend
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
86/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.