Jump to solution
Verify

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.

Jump to Verify Open PR/Commit
@@ -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)
repro.py
# 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)
verify
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.
fix.md
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”
@georgepsarakis · 2020-06-27 · source
“> 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…”
@auvipy · 2022-06-30 · source
“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(),…”
@youtux · 2023-03-06 · source
“**TL;DR:** Unpickleable errors can cause the celery queue to crash. The queue should log a warning and continue operating.”
@caleb15 · 2020-06-23 · source

Failure Signature (Search String)

  • AttributeError billiard.reduction in loadbuf

Error Message

Stack trace
error.txt
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.txt
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

repro.py
# 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

When NOT to use: Do not use this fix if your application relies on unhandled exceptions being propagated.

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.

Get updates

We publish verified fixes weekly. No spam.

Subscribe

When NOT to Use This Fix

  • Do not use this fix if your application relies on unhandled exceptions being propagated.

Verify Fix

verify
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

VersionStatus
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.