The Fix
pip install celery==4.4.0rc5
Based on closed celery/celery issue #5411 · PR/commit linked
Production note: Most teams hit this during upgrades or environment changes. Roll out with a canary and smoke critical endpoints (health, OpenAPI/docs) before 100%.
@@ -207,8 +207,8 @@ def remaining(start, ends_in, now=None, relative=False):
"""
now = now or datetime.utcnow()
- if now.utcoffset() != start.utcoffset():
- # Timezone has changed, or DST started/ended
+ if str(start.tzinfo) == str(now.tzinfo) and now.utcoffset() != start.utcoffset():
Option A — Upgrade to fixed release\npip install celery==4.4.0rc5\nWhen NOT to use: Do not apply this fix if the timezone handling logic is already correct in your version.\n\n
Why This Fix Works in Production
- Trigger: So, I think `start = start.replace(tzinfo=now.tzinfo)` must be changed to `start = start.astimezone(now.tzinfo)`.
- Mechanism: The remaining function incorrectly handled timezone conversion using replace instead of astimezone
- Why the fix works: Fixes bug 5411 by correcting the timezone handling in the remaining function of celery.utils.time.py. (first fixed release: 4.4.0rc5).
- 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.5.2 in real deployments (not just unit tests).
- The remaining function incorrectly handled timezone conversion using replace instead of astimezone
- Production symptom (often without a traceback): So, I think `start = start.replace(tzinfo=now.tzinfo)` must be changed to `start = start.astimezone(now.tzinfo)`.
Proof / Evidence
- GitHub issue: #5411
- Fix PR: https://github.com/celery/celery/pull/5462
- First fixed release: 4.4.0rc5
- 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.70
Discussion
High-signal excerpts from the issue thread (symptoms, repros, edge-cases).
“So, I think the bug can be resolved by just removing the following lines https://github.com/celery/celery/blob/59547c5ccb78d2f30d53cb7fedf9db147f2153c8/celery/utils/time.py#L210-L212 The reason is that even if both the start and…”
“Hey, I just found that in 5.0-devel branch, the above mentioned lines have already been removed”
“hey..I can do that. Can you please tell me how to add a test and give PR (I know about issuing PR but not sure…”
“Just need some clarification on the specification about scheduling: Suppose user in America/Los_Angeles timezone schedules a task to run like this (he schedules during summer):…”
Failure Signature (Search String)
- So, I think `start = start.replace(tzinfo=now.tzinfo)` must be changed to `start = start.astimezone(now.tzinfo)`.
- So, I hope there is no need for a PR (for this minor change).
Copy-friendly signature
Failure Signature
-----------------
So, I think `start = start.replace(tzinfo=now.tzinfo)` must be changed to `start = start.astimezone(now.tzinfo)`.
So, I hope there is no need for a PR (for this minor change).
Error Message
Signature-only (no traceback captured)
Error Message
-------------
So, I think `start = start.replace(tzinfo=now.tzinfo)` must be changed to `start = start.astimezone(now.tzinfo)`.
So, I hope there is no need for a PR (for this minor change).
Environment
- Python: 3.5.2
What Broke
Incorrect time calculations leading to scheduling errors in tasks across different timezones.
Why It Broke
The remaining function incorrectly handled timezone conversion using replace instead of astimezone
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.
Fix reference: https://github.com/celery/celery/pull/5462
First fixed release: 4.4.0rc5
Last verified: 2026-02-09. Validate in your environment.
When NOT to Use This Fix
- Do not apply this fix if the timezone handling logic is already correct in your version.
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.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.