Repository navigation
Tasks are immediately restarted after unknown "Server indicated the task shouldn't be running anymore", resulting in HTTP 409 #59378
Description
Apache Airflow version
Other Airflow 2/3 version (please specify below)
If "Other Airflow 2/3 version" selected, which one?
apache/airflow:3.1.3 Docker image
What happened?
We're seeing an issue where a task is started, stopped b/c Airflow thinks it should be not be running, then attempts multiple restarts of the task. This results in the task starting execution multiple times, but it appears that Airflow loses track of (or ignores) the execution result. Note that the requests to restart occur within (milli)seconds of the task first starting. In some cases, there are several retries (11x), and the dag is marked as Failed though the offending tasks are marked as Skipped, when they clearly have been attempted multiple times.
Our deployment of Airflow has two instances of the Scheduler running, and we've seen this error occur both when the task is re/started from the same instance, and when it has been re/started from different instances of the Scheduler.
One example of the sequence of Scheduler log entries are as follows. There does not appear to be any other relevant or associated logs within the time frame, but I can provide any further logs if requested. In this case, there are no indications of any error or restart of the tasks in the Dag run logs.
[2025-12-08T08:00:01.522+0000] {{_client.py:1026}} INFO - HTTP Request: PATCH http://myinstance/execution/task-instances/019afcf9-7ee5-713b-be96-758c026e7d15/run "HTTP/1.1 200 OK"
2025-12-08 08:00:01 [debug ] Sending [supervisor] msg=StartupDetails(ti=TaskInstance(id=UUID('019afcf9-7ee5-713b-be96-758c026e7d15'), task_id='MyTask', dag_id='MyDag', run_id='scheduled__2025-12-07T08:00:00+00:00', try_number=1, ...
[2025-12-08T08:01:22.494+0000] {{_client.py:1026}} INFO - HTTP Request: PATCH http://myinstance/execution/task-instances/019afcf9-7ee5-713b-be96-758c026e7d15/run "HTTP/1.1 200 OK"
2025-12-08 08:01:22 [debug ] Sending [supervisor] msg=StartupDetails(ti=TaskInstance(id=UUID('019afcf9-7ee5-713b-be96-758c026e7d15'), task_id='MyTask', dag_id='MyDag', run_id='scheduled__2025-12-07T08:00:00+00:00', try_number=2
[2025-12-08T08:01:22.239+0000] {{_client.py:1026}} INFO - HTTP Request: PUT http://myinstance/execution/task-instances/019afcf9-7ee5-713b-be96-758c026e7d15/heartbeat "HTTP/1.1 409 Conflict"
2025-12-08 08:01:22 [error ] Server indicated the task shouldn't be running anymore [supervisor] detail={'detail': {'reason': 'not_running', 'message': 'TI is no longer in the running state and task should terminate', 'current_state': 'scheduled'}} status_code=409 ti_id=UUID('019afcf9-7ee5-713b-be96-758c026e7d15')
[2025-12-08T08:01:22.642+0000] {{_client.py:1026}} INFO - HTTP Request: PUT http://myinstance/execution/task-instances/019afcf9-7ee5-713b-be96-758c026e7d15/rtif "HTTP/1.1 201 Created"
Occasionally, the dag logs will output something like the following before restarting the task:
2025-12-08 01:18:04.771 | Server indicated the task shouldn't be running anymore. Terminating process
2025-12-08 01:18:04.771 | Task killed!
What you think should happen instead?
No response
How to reproduce
Seems to occur sporadically, and not in any consistent manner. The dags with which this occurs also varies.
Operating System
Debian GNU/Linux 12 (bookworm)
Versions of Apache Airflow Providers
apache-airflow-providers-fab == 3.0.2
apache-airflow-providers-google == 15.1.0
apache-airflow-providers-slack == 9.5.0
apache-airflow-providers-standard == 1.9.0
Deployment
Other Docker-based deployment
Deployment details
There are two instances of Airflow Scheduler deployed
Anything else?
No response
Are you willing to submit PR?
- Yes I am willing to submit a PR!
Code of Conduct
- I agree to follow this project's Code of Conduct
Activity
boring-cyborg commentedon Dec 12, 2025
Thanks for opening your first issue here! Be sure to follow the issue template! If you are willing to raise PR to address this issue please do so, no need to wait for approval.
danielford831 commentedon Dec 17, 2025
Also seeing this on 3.1.4 (which I'll bump to 3.1.5 today, but I notice @rjh-yext is on 3.1.3 so hopefully unrelated)
2 schedulers on EKS. also useful to note there's no mention of an attempt 1 in the audit log and the UI, but the log for attempt 1 is populated in EFS, attempt 2 log is empty
davidmarshmallow commentedon Dec 17, 2025
Also seeing this on 3.1.4
vinitpayal commentedon Dec 17, 2025
Same for us in Airflow 3.1.4.
In UI randomly seeing task_number starting from 11, 16 etc and because of which task retries we are setting aren't working.
Screenshot for reference(only one retry with try number 11)
Same is the case in metadata database as well
guillaumecollombet commentedon Dec 18, 2025
Same thing in 3.1.5
abhijeets25012-tech commentedon Dec 26, 2025
Scheduler A Scheduler B
| |
RUNNING |
| |
Task starts |
| |
|--------------> SCHEDULED
| |
Heartbeat (409) |
| |
Task killed & retried |
I’m new to open source and this is my first PR, so feedback is very welcome.
While investigating an issue with multiple schedulers, I observed that a
TaskInstance can regress from RUNNING back to SCHEDULED due to a race condition.
This leads to heartbeat conflicts (409), premature task termination, and
repeated task retries.
This PR adds a small guard in TaskInstance.set_state() to prevent the invalid
RUNNING → SCHEDULED transition while allowing all valid state transitions.
This avoids killing already-running tasks and preserves correct execution.
Tested locally with a multi-scheduler setup.
dabla commentedon Jan 14, 2026
@abhijeets25012-tech I can't find the PR you're mentioning?
dabla commentedon Jan 14, 2026
Issue still there with Airflow 3.1.6, running with 3 schedulers:
dabla commentedon Jan 14, 2026
In the meantime found another related issue #5761.
bohdan-pd commentedon Jan 26, 2026
Same thing in airflow 3.0.6
vin-c-ent commentedon Feb 11, 2026
same here, airflow 3.1.3 with 4 schedulers
8 remaining items
Fix ti_skip_downstream overwriting RUNNING tasks to SKIPPED
Fix ti_skip_downstream overwriting RUNNING tasks to SKIPPED
Fix ti_skip_downstream overwriting RUNNING tasks to SKIPPED
Fix ti_skip_downstream overwriting RUNNING tasks to SKIPPED
sam-dumont commentedon Mar 13, 2026
We hit this on our prod cluster (830 DAGs, ~25k tasks/day, 2 schedulers, KubernetesExecutor, ~500 peak concurrent workers on EKS) and spent 2+ weeks instrumenting it. Sharing what we found in case it helps.
We traced it to at least 2 independent race conditions, both unguarded UPDATEs on task instance state that can overwrite a RUNNING task :
schedule_tis()indagrun.py: a competing scheduler overwrites RUNNING → SCHEDULED. Worker heartbeats, gets 409 withcurrent_state: scheduled, task killed. PR Fix duplicate task execution when running multiple schedulers (HA) #60330 by @ephraimbuddy addresses this.ti_skip_downstream()in the Execution API :BranchOperatormarks unchosen tasks as SKIPPED, but the UPDATE has no state guard, so it can overwrite tasks already RUNNING. Worker heartbeats, gets 409 withcurrent_state: skipped, task killed. We opened PR Fix ti_skip_downstream overwriting RUNNING tasks to SKIPPED #63266 for this one.Both seem to exist in every Airflow 3.x release with 2+ schedulers. The frequency likely scales with concurrency : more schedulers and more tasks = wider race window.
What worked for us :
We patched both code paths at Docker build time (patching the installed
.pyfiles so every process gets the fix). Ourapply_patches.pyscript does this (auto-detects already-patched files, self-disables when upstream fix lands). Got us from 374 errors/day to 0.One thing we learned the hard way : monkey patches in
airflow_local_settings.pyworked forschedule_tis()(runs in the scheduler) but NOT forti_skip_downstream(). That one runs on the API server (FastAPI/uvicorn), which has a different startup path and never importsairflow_local_settings.py. We had zero 409s for 18h, thenskipped409s exploded to 131/day when load increased. Build-time patching was the only approach that covered all processes.Diagnosing which vector you're hitting :
Parsing the
current_statefield from the 409 response body was the key to telling them apart :current_statescheduledschedule_tis()race : RUNNING → SCHEDULEDfailedskippedti_skip_downstream()race : RUNNING → SKIPPED (branching DAGs)not_foundOur timeline (2+ weeks of continuous monitoring) :
schedule_tispatch deployed :scheduled+faileddropped to 0skippedremainingNote if you're on 3.1.7 specifically : on top of the race conditions above, 3.1.7 has a missing
task_rescheduleindex +DepContextmutation leak (#59604) that slows the scheduler, grows memory (ours peaked at 5.92/6 GiB), and widens the race window for both bugs. This created a feedback loop on our cluster where 409s escalated exponentially (5 → 26 → 133 → 374/day). Upgrading to 3.1.8 broke the loop (#60931, #62089), but the race conditions still need the patches on top.Related PRs :
schedule_tis()state guardti_skip_downstream()state guard(AI-assisted investigation with Claude Code. All monitoring data from our prod cluster.)
dabla commentedon Mar 13, 2026
Nice investigation and explanation, we don’t have those problems as often anymore. Will try do do the same at our side and see if it also fixes the issue.
We are running with 3 concurrent schedulers but since we now migrated from YugabyteDB to Postgres again that maybe also helped already. As YugabyteDB isn’t officially supported on Airflow we had to do some post alterations to make it run correctly on YugabyteDB as the Airflow migrations scripts aren’t optimized for it.
We are running on 3.1.8 so that may also help improve it as you stated in your comment.
bohdan-pd commentedon Mar 16, 2026
@sam-dumont Thank you! I tested your patch on MWAA and still got this error. Maybe there is another bug as well:
TI is no longer in the running state and task should terminatesam-dumont commentedon Mar 16, 2026
Oh too bad 😔 we still have a few 409 but they are legitimate timeouts (explicit timeouts at the task level). I haven't use MWAA in a while so I'm not sure how easy it is to patch, do you have any control over the docker images?
If you have control over the airflow_local_settings.py you can use the monkeypatch in this gist : https://gist.github.com/sam-dumont/c362da9c42dd5930266c855c4b8e42fa
The first one only, the second does not work as it's running on the api server.
From what I remember MWAA was quite limited in customization and this is why we took the 'custom' road, but we tested 3 years ago so it probably changed since them.
Hope it'll help... 🤞
Fix ti_skip_downstream overwriting RUNNING tasks to SKIPPED
Fix downstream tasks being incorrectly skipped in HA scheduler mode (a…
Fix downstream tasks being incorrectly skipped in HA scheduler mode (a…
Fix downstream tasks being incorrectly skipped in HA scheduler mode (a…
Fix downstream tasks being incorrectly skipped in HA scheduler mode (a…