The Fix
pip install celery==5.3.0rc1
Based on closed celery/celery issue #6185 · 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.
@@ -219,7 +219,7 @@ def handle_failure(self, task, req, store_errors=True, call_errbacks=True):
# make sure we only send pickleable exceptions back to parent.
einfo = ExceptionInfo()
- einfo.exception = get_pickleable_exception(einfo.exception)
+ einfo.exception.exc = get_pickleable_exception(einfo.exception.exc)
einfo.type = get_pickleable_etype(einfo.type)
# tasks.py
from celery import Celery
app = Celery("tasks", broker="redis://localhost:6379/0", backend="redis://localhost:6379/0")
class BadException(Exception):
def __init__(self, message, code):
super().__init__(message)
self.code = code
@app.task(bind=True)
def add(self):
raise self.retry(exc=BadException("foo", "bar"), countdown=1, max_retries=1)
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.0rc1\nWhen NOT to use: Do not use this fix if your application relies on unhandled exceptions being propagated.\n\n
Why This Fix Works in Production
- Trigger: AttributeError billiard.reduction in loadbuf
- Mechanism: Unpickleable exceptions were not handled correctly during task retries, causing worker crashes
- Why the fix works: Fix celery worker crash when a retry is issued with an unpickleable exception. (first fixed release: 5.3.0rc1).
Why This Breaks in Prod
- Shows up under Python 3.7 in real deployments (not just unit tests).
- Unpickleable exceptions were not handled correctly during task retries, causing worker crashes
- Surfaces as: AttributeError billiard.reduction in loadbuf
Proof / Evidence
- GitHub issue: #6185
- Fix PR: https://github.com/celery/celery/pull/8133
- First fixed release: 5.3.0rc1
- Reproduced locally: No (not executed)
- Last verified: 2026-02-09
- Confidence: 0.85
- 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).
“Hello @caleb15”
“> site-packages/django/test/runner.py", line 104, in _confirm_picklable > pickle.loads(pickle.dumps(obj)) > AttributeError: can't set attribute yes, for that reason, we still keep the issue open, but you…”
“To me, it seems that it only happens when using retry logic with an unpicklable exception (e.g. doing a self.retry(MyUnpicklableException())). If I just raise MyUnpicklableException(),…”
“**TL;DR:** Unpickleable errors can cause the celery queue to crash. The queue should log a warning and continue operating.”
Failure Signature (Search String)
- AttributeError billiard.reduction in loadbuf
Error Message
Stack trace
Error Message
-------------
AttributeError billiard.reduction in loadbuf
Error on stopping Pool: "AttributeError(\"can't set attribute\")"
billiard/reduction.py in loadbuf at line 61
billiard/connection.py in recv at line 279
celery/concurrency/asynpool.py in _flush_outqueue at line 412
celery/concurrency/asynpool.py in iterate_file_descriptors_safely at line 240
celery/concurrency/asynpool.py in on_stop_not_started at line 387
billiard/pool.py in stop at line 526
billiard/pool.py in stop_if_not_current at line 145
billiard/pool.py in join at line 1622
celery/concurrency/prefork.py in on_stop at line 145
celery/concurrency/base.py in stop at line 123
celery/bootsteps.py in stop at line 373
celery/bootsteps.py in send_all at line 151
Stack trace
Error Message
-------------
test_update_billing_add_ons_ignores_simultaneous_request_error (ff.mods.billing.tests.test_subscription_logic.UpdateBillingAddOnsTestCase) failed:
ValidationError(b'<?xml version="1.0" encoding="UTF-8"?>\n<error>\n
<symbol>simultaneous_request</symbol>\n <description>A change for
subscription 456ee8a3881160536ad68346fe91eede is already in
progress.</description>\n</error>')
Unfortunately, the exception it raised cannot be pickled, making it impossible
for the parallel test runner to handle it cleanly.
Here's the error encountered while trying to pickle the exception:
AttributeError("can't set attribute")
You should re-run this test with the --parallel=1 option to reproduce the
failure and get a correct traceback.
Destroying test database for alias 'default'...
TOTAL RUNTIME: 67.09s
TOTAL RUNTIME: 67.09s
multiprocessing.pool.RemoteTraceback:
"""
Traceback (most recent call last):
File "/usr/local/lib/python3.7/multiprocessing/pool.py", line 121, in worker
result = (True, func(*args, **kwds))
File "/home/circleci/project/venv/lib/python3.7/site-packages/django/test/runner.py", line 309, in _run_subsuite
result = runner.run(subsuite)
File "/home/circleci/project/venv/lib/python3.7/site-packages/django/test/runner.py", line 256, in run
test(result)
File "/usr/local/lib/python3.7/unittest/suite.py", line 84, in __call__
return self
... (truncated) ...
Minimal Reproduction
# tasks.py
from celery import Celery
app = Celery("tasks", broker="redis://localhost:6379/0", backend="redis://localhost:6379/0")
class BadException(Exception):
def __init__(self, message, code):
super().__init__(message)
self.code = code
@app.task(bind=True)
def add(self):
raise self.retry(exc=BadException("foo", "bar"), countdown=1, max_retries=1)
Environment
- Python: 3.7
What Broke
Workers crashloop when tasks raise unpickleable exceptions during retries.
Why It Broke
Unpickleable exceptions were not handled correctly during task retries, causing worker crashes
Fix Options (Details)
Option A — Upgrade to fixed release Safe default (recommended)
pip install celery==5.3.0rc1
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/8133
First fixed release: 5.3.0rc1
Last verified: 2026-02-09. Validate in your environment.
When NOT to Use This Fix
- Do not use this fix if your application relies on unhandled exceptions being propagated.
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 |
|---|---|
| 5.3.0rc1 | Fixed |
Related Issues
No related fixes found.
Sources
We don’t republish the full GitHub discussion text. Use the links above for context.