The Fix
pip install celery==4.4.0rc5
Based on closed celery/celery issue #5597 · PR/commit linked
@@ -193,6 +193,8 @@ def apply(self, args=None, kwargs=None, **options):
args = args if args else ()
kwargs = kwargs if kwargs else {}
+ # Extra options set to None are dismissed
+ options = {k: v for k, v in options.items() if v is not None}
# For callbacks: extra args are prepended to the stored args.
from kombu import Queue, Exchange
from celery import Celery
import time
broker = "amqp://admin:admin@localhost:5672/mqfrontend"
app = Celery(
"test celery",
broker=broker
)
app.conf.accept_content = ['json']
app.conf.task_serializer = 'json'
app.conf.result_serializer = 'json'
app.conf.task_ignore_result = True
app.conf.task_routes = {'frontend.*': {'queue': 'first_task', 'routing_key': 'frontend.first_task'}}
app.conf.task_queues = (
Queue('first_task', routing_key='frontend.first_task', queue_arguments={'x-max-priority': 10}),
)
@app.task(name="frontend.first_task", bind=True)
def priority_task(self, arg):
time.sleep(2)
print("PRIORITY: i:%s, p:%s"%(arg, self.request.delivery_info['priority']))
return self.request.delivery_info['priority']
@app.task(name="frontend.second_task", bind=True)
def priorityb_task(self, _, arg):
time.sleep(2)
print("PRIORITYB: i:%s, p:%s"%(arg, self.request.delivery_info['priority']))
return "Test%s"%self.request.delivery_info['priority']
if __name__=='__main__':
import celery
s = celery.chain(
app.signature(
"frontend.first_task",
args=(5,),
priority=5
),
app.signature(
"frontend.second_task",
args=(5,),
priority=5
)
)
s.delay()
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.
Option A — Upgrade to fixed release\npip install celery==4.4.0rc5\nWhen NOT to use: Do not use this fix if the task priority needs to be inherited from parent tasks.\n\nOption B — Safe version pin\npip install celery==4.2.1\nWhen NOT to use: Do not use if you need features or security fixes in newer releases.\n\n
Why This Fix Works in Production
- Trigger: Please include a backtrace and surround it with triple backticks (```).
- Mechanism: The chain loses priority due to extra options being set to None and not dismissed
- Why the fix works: Fixes the issue where the chain loses priority by ensuring that extra options set to None are dismissed. (first fixed release: 4.4.0rc5).
- If left unfixed, this can cause silent data inconsistencies that propagate (bad cache entries, incorrect downstream decisions).
Why This Breaks in Prod
- The chain loses priority due to extra options being set to None and not dismissed
- Production symptom (often without a traceback): from kombu import Queue, Exchange
Proof / Evidence
- GitHub issue: #5597
- Fix PR: https://github.com/celery/celery/pull/5759
- Fix commit: https://github.com/celery/celery/commit/7204e13ddcc09a03beb306c9b13f920b4d50f743
- First fixed release: 4.4.0rc5
- Reproduced locally: No (not executed)
- Last verified: 2026-02-09
- Confidence: 0.75
- Did this fix it?: Yes (upstream fix exists)
- Own content ratio: 0.37
Discussion
High-signal excerpts from the issue thread (symptoms, repros, edge-cases).
“@olii why does a regular task pass task_priority=None? It should just _not pass it_, right? It's also strange that args/kwargs are merged with options. I…”
“I would say that some piece of code "abused" the fact that kwargs were ignored, intentionally or not, and the change in #4952 revealed that…”
“If this worked in older versions, could you try this in current master? and find the root cause of the regression?”
“This one looks interesting -- will take a look probably this week.”
Failure Signature (Search String)
- Please include a backtrace and surround it with triple backticks (```).
Copy-friendly signature
Failure Signature
-----------------
from kombu import Queue, Exchange
Please include a backtrace and surround it with triple backticks (```).
Error Message
Signature-only (no traceback captured)
Error Message
-------------
from kombu import Queue, Exchange
Please include a backtrace and surround it with triple backticks (```).
Minimal Reproduction
from kombu import Queue, Exchange
from celery import Celery
import time
broker = "amqp://admin:admin@localhost:5672/mqfrontend"
app = Celery(
"test celery",
broker=broker
)
app.conf.accept_content = ['json']
app.conf.task_serializer = 'json'
app.conf.result_serializer = 'json'
app.conf.task_ignore_result = True
app.conf.task_routes = {'frontend.*': {'queue': 'first_task', 'routing_key': 'frontend.first_task'}}
app.conf.task_queues = (
Queue('first_task', routing_key='frontend.first_task', queue_arguments={'x-max-priority': 10}),
)
@app.task(name="frontend.first_task", bind=True)
def priority_task(self, arg):
time.sleep(2)
print("PRIORITY: i:%s, p:%s"%(arg, self.request.delivery_info['priority']))
return self.request.delivery_info['priority']
@app.task(name="frontend.second_task", bind=True)
def priorityb_task(self, _, arg):
time.sleep(2)
print("PRIORITYB: i:%s, p:%s"%(arg, self.request.delivery_info['priority']))
return "Test%s"%self.request.delivery_info['priority']
if __name__=='__main__':
import celery
s = celery.chain(
app.signature(
"frontend.first_task",
args=(5,),
priority=5
),
app.signature(
"frontend.second_task",
args=(5,),
priority=5
)
)
s.delay()
What Broke
Tasks in a chain do not respect priority settings, leading to unexpected execution order.
Why It Broke
The chain loses priority due to extra options being set to None and not dismissed
Fix Options (Details)
Option A — Upgrade to fixed release Safe default (recommended)
pip install celery==4.4.0rc5
Use when you can deploy the upstream fix. It is usually lower-risk than long-lived workarounds.
Option B — Safe version pin Backward-compatible pin
pip install celery==4.2.1
Use when you can’t upgrade immediately. Plan a follow-up to upgrade (pins can accumulate security/compat debt).
Fix reference: https://github.com/celery/celery/pull/5759
First fixed release: 4.4.0rc5
Last verified: 2026-02-09. Validate in your environment.
When NOT to Use This Fix
- Do not use this fix if the task priority needs to be inherited from parent tasks.
- Do not use if you need features or security fixes in newer releases.
Verify Fix
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.
Did This Fix Work in Your Case?
Quick signal helps us prioritize which fixes to verify and improve.
Prevention
- Capture the exact failing error string in logs and tests so you can reproduce via a minimal script.
- Pin production dependencies and upgrade only with a reproducible test that hits the failing path.
Version Compatibility Table
| Version | Status |
|---|---|
| 4.2.1 | Working |
| 4.4.0rc5 | Fixed |
Related Issues
No related fixes found.
Sources
We don’t republish the full GitHub discussion text. Use the links above for context.