The Fix
pip install celery==5.3.4
Based on closed celery/celery issue #8456 · PR/commit linked
Production note: This usually shows up under retries/timeouts. Treat it as a side-effect risk until you can verify behavior with a canary + real traffic.
@@ -653,7 +653,7 @@ def stamp_links(self, visitor, append_stamps=False, **headers):
# Stamp all of the callbacks of this signature
headers = deepcopy(non_visitor_headers)
- for link in self.options.get('link', []) or []:
+ for link in maybe_list(self.options.get('link')) or []:
link = maybe_signature(link, app=self.app)
from celery import Celery, chain, group, chord
app = Celery('tasks', broker='redis://localhost/', backend='redis://localhost/')
app.conf.task_allow_error_cb_on_chord_header = True
@app.task
def fake_work_unit(x):
raise Exception
@app.task
def nothing_work_unit():
return "hi"
@app.task
def fake_error_handler(*args):
print("oops")
def test():
f = app.signature(
"test_celery.nothing_work_unit",
immutable=True,
)
f2 = app.signature(
"test_celery.fake_error_handler",
)
# This formulation works correctly...
# chain(
# f.on_error(f2),
# group(
# app.signature(
# "test_celery.fake_work_unit",
# args=(1,),
# immutable=True,
# ),
# app.signature(
# "test_celery.fake_work_unit",
# args=(2,),
# immutable=True,
# ),
# ).on_error(f2),
# f.on_error(f2),
# ).apply_async()
# ...but not this one.
chain(
f,
group(
app.signature(
"test_celery.fake_work_unit",
args=(1,),
immutable=True,
),
app.signature(
"test_celery.fake_work_unit",
args=(2,),
immutable=True,
),
),
f,
).on_error(f2).apply_async()
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==5.3.4\nWhen NOT to use: Do not apply this fix if task_allow_error_cb_on_chord_header is disabled.\n\n
Why This Fix Works in Production
- Trigger: >> from test_celery import test
- Mechanism: The code incorrectly handled task links and error callbacks in a rewritten chain
- Why the fix works: Fixed an AttributeError that occurred when using link_error/on_error on a rewritten chain with task_allow_error_cb_on_chord_header enabled. (first fixed release: 5.3.4).
- If left unfixed, the same config can fail only in production (env differences), causing startup failures or partial feature outages.
Why This Breaks in Prod
- Shows up under Python 3.10 in real deployments (not just unit tests).
- The code incorrectly handled task links and error callbacks in a rewritten chain
- Surfaces as: >> from test_celery import test
Proof / Evidence
- GitHub issue: #8456
- Fix PR: https://github.com/celery/celery/pull/8463
- First fixed release: 5.3.4
- Reproduced locally: No (not executed)
- Last verified: 2026-02-09
- Confidence: 0.95
- Did this fix it?: Yes (upstream fix exists)
- Own content ratio: 0.29
Discussion
High-signal excerpts from the issue thread (symptoms, repros, edge-cases).
“Thank you for the informed report! I'll check it out in the next few days.”
Failure Signature (Search String)
- >> from test_celery import test
Error Message
Stack trace
Error Message
-------------
>> from test_celery import test
>> test()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/asteinborn/Ramp/misc/celery-test/test_celery.py", line 68, in test
).on_error(f2).apply_async()
File "/Users/asteinborn/Ramp/misc/celery-test/venv/lib/python3.10/site-packages/celery/canvas.py", line 1035, in apply_async
return self.run(args, kwargs, app=app, **(
File "/Users/asteinborn/Ramp/misc/celery-test/venv/lib/python3.10/site-packages/celery/canvas.py", line 1060, in run
tasks, results_from_prepare = self.prepare_steps(
File "/Users/asteinborn/Ramp/misc/celery-test/venv/lib/python3.10/site-packages/celery/canvas.py", line 1246, in prepare_steps
task.link_error(errback)
File "/Users/asteinborn/Ramp/misc/celery-test/venv/lib/python3.10/site-packages/celery/canvas.py", line 2276, in link_error
task.link_error(errback.clone(immutable=True))
AttributeError: 'str' object has no attribute 'link_error'
Minimal Reproduction
from celery import Celery, chain, group, chord
app = Celery('tasks', broker='redis://localhost/', backend='redis://localhost/')
app.conf.task_allow_error_cb_on_chord_header = True
@app.task
def fake_work_unit(x):
raise Exception
@app.task
def nothing_work_unit():
return "hi"
@app.task
def fake_error_handler(*args):
print("oops")
def test():
f = app.signature(
"test_celery.nothing_work_unit",
immutable=True,
)
f2 = app.signature(
"test_celery.fake_error_handler",
)
# This formulation works correctly...
# chain(
# f.on_error(f2),
# group(
# app.signature(
# "test_celery.fake_work_unit",
# args=(1,),
# immutable=True,
# ),
# app.signature(
# "test_celery.fake_work_unit",
# args=(2,),
# immutable=True,
# ),
# ).on_error(f2),
# f.on_error(f2),
# ).apply_async()
# ...but not this one.
chain(
f,
group(
app.signature(
"test_celery.fake_work_unit",
args=(1,),
immutable=True,
),
app.signature(
"test_celery.fake_work_unit",
args=(2,),
immutable=True,
),
),
f,
).on_error(f2).apply_async()
Environment
- Python: 3.10
What Broke
Users experienced AttributeError when using link_error/on_error with task_allow_error_cb_on_chord_header enabled.
Why It Broke
The code incorrectly handled task links and error callbacks in a rewritten chain
Fix Options (Details)
Option A — Upgrade to fixed release Safe default (recommended)
pip install celery==5.3.4
Use when you can deploy the upstream fix. It is usually lower-risk than long-lived workarounds.
Fix reference: https://github.com/celery/celery/pull/8463
First fixed release: 5.3.4
Last verified: 2026-02-09. Validate in your environment.
When NOT to Use This Fix
- Do not apply this fix if task_allow_error_cb_on_chord_header is disabled.
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
- Make timeouts explicit and test them (unit + integration) to avoid silent behavior changes.
- Instrument retries (attempt count + reason) and alert on spikes to catch dependency slowdowns.
Version Compatibility Table
| Version | Status |
|---|---|
| 5.3.4 | Fixed |
Related Issues
No related fixes found.
Sources
We don’t republish the full GitHub discussion text. Use the links above for context.