notifications: bulk_create missing ignore_conflicts causes duplicate in-app notifications on Celery task retry
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
- A Celery worker processes the
otifications task and crashes after ulk_create (before ACK). - The broker re-queues the task. The second worker runs the same task for the same event.
- Notification.objects.bulk_create succeeds again (no unique constraint to block it).
- 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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