The Fix
pip install celery==5.5.0
Based on closed celery/celery issue #9613 · 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.
@@ -359,6 +359,11 @@ def _params_from_url(self, url, defaults):
return connparams
+ def exception_safe_to_retry(self, exc):
+ if isinstance(exc, self.connection_errors):
+ return True
try:
from redis import exceptions
except ImportError:
exceptions = None
class test_RedisBackend(basetest_RedisBackend):
def test_store_result_with_retries(self):
self.app.conf.result_backend_always_retry, prev = True, self.app.conf.result_backend_always_retry
try:
b = self.Backend(app=self.app)
# b.exception_safe_to_retry = lambda exc: True
b._sleep = Mock()
b._get_task_meta_for = Mock()
b._get_task_meta_for.return_value = {
'status': states.RETRY,
'result': {
"exc_type": "Exception",
"exc_message": ["failed"],
"exc_module": "builtins",
},
}
b._store_result = Mock()
b._store_result.side_effect = [
exceptions.ConnectionError("failed"),
42
]
res = b.store_result("testing", 42, states.SUCCESS) # raises redis.exceptions.ConnectionError: failed
assert res == 42
assert b._sleep.call_count == 1
finally:
self.app.conf.result_backend_always_retry = prev
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.5.0\nWhen NOT to use: Do not use this fix if the behavior of result_backend_always_retry is not intended to change.\n\n
Why This Fix Works in Production
- Trigger: RedisBackend does not retry on store_result even with result_backend_always_retry=True
- Mechanism: The exception_safe_to_retry method was not defined for RedisBackend, preventing retries on store_result
- Why the fix works: Defines the exception_safe_to_retry method for RedisBackend to ensure that operations like store_result retry correctly when result_backend_always_retry is set to True. (first fixed release: 5.5.0).
- 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
- Triggered by an upgrade/regression window: 1.1–2.4.0 breaks; 5.5.0 is the first fixed release.
- The exception_safe_to_retry method was not defined for RedisBackend, preventing retries on store_result
- Production symptom (often without a traceback): RedisBackend does not retry on store_result even with result_backend_always_retry=True
Proof / Evidence
- GitHub issue: #9613
- Fix PR: https://github.com/celery/celery/pull/9614
- First fixed release: 5.5.0
- Affected versions: 1.1–2.4.0
- 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.48
Discussion
High-signal excerpts from the issue thread (symptoms, repros, edge-cases).
“<!-- Please fill this template entirely and do not erase parts of it. We reserve the right to close without a response bug reports which are incomplete. --> # Checklist <!-- To check an item on the list replace [ ] with [x]. --> - [x] I hav”
Failure Signature (Search String)
- RedisBackend does not retry on store_result even with result_backend_always_retry=True
- - [x] I have included all related issues and possible duplicate issues
Copy-friendly signature
Failure Signature
-----------------
RedisBackend does not retry on store_result even with result_backend_always_retry=True
- [x] I have included all related issues and possible duplicate issues
Error Message
Signature-only (no traceback captured)
Error Message
-------------
RedisBackend does not retry on store_result even with result_backend_always_retry=True
- [x] I have included all related issues and possible duplicate issues
Minimal Reproduction
try:
from redis import exceptions
except ImportError:
exceptions = None
class test_RedisBackend(basetest_RedisBackend):
def test_store_result_with_retries(self):
self.app.conf.result_backend_always_retry, prev = True, self.app.conf.result_backend_always_retry
try:
b = self.Backend(app=self.app)
# b.exception_safe_to_retry = lambda exc: True
b._sleep = Mock()
b._get_task_meta_for = Mock()
b._get_task_meta_for.return_value = {
'status': states.RETRY,
'result': {
"exc_type": "Exception",
"exc_message": ["failed"],
"exc_module": "builtins",
},
}
b._store_result = Mock()
b._store_result.side_effect = [
exceptions.ConnectionError("failed"),
42
]
res = b.store_result("testing", 42, states.SUCCESS) # raises redis.exceptions.ConnectionError: failed
assert res == 42
assert b._sleep.call_count == 1
finally:
self.app.conf.result_backend_always_retry = prev
What Broke
Operations like store_result fail without retrying, causing potential data loss.
Why It Broke
The exception_safe_to_retry method was not defined for RedisBackend, preventing retries on store_result
Fix Options (Details)
Option A — Upgrade to fixed release Safe default (recommended)
pip install celery==5.5.0
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/9614
First fixed release: 5.5.0
Last verified: 2026-02-09. Validate in your environment.
When NOT to Use This Fix
- Do not use this fix if the behavior of result_backend_always_retry is not intended to change.
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 |
|---|---|
| 1.1 | Broken |
| 2.4.0 | Broken |
| 5.5.0 | Fixed |
Related Issues
No related fixes found.
Sources
We don’t republish the full GitHub discussion text. Use the links above for context.