Repository navigation
Discard the task state values for a task instance when it is cleared - #72100
Merged
Merged
Conversation
amoghrajesh
requested review from
bbovenzi,
bugraoz93,
choo121600,
dheerajturaga,
ephraimbuddy,
guan404ming,
henry3260,
jason810496,
pierrejeambrun,
potiuk,
rawwar,
ryanahamilton,
shubhamraj-git and
vatsrahul1001
as code owners
August 26, 2026 13:44
ashb
reviewed
Aug 26, 2026
kaxil
reviewed
Sep 14, 2026
cmarteepants
approved these changes
Sep 18, 2026
kaxil
reviewed
Sep 18, 2026
Contributor
Author
|
@kaxil would you mind taking another look at this? |
Contributor
Author
|
@kaxil can you take a look at this, trying to make this for 3.4 |
kaxil
reviewed
Sep 28, 2026
amoghrajesh
force-pushed
the
task-state-clear-on-clear
branch
from
September 28, 2026 13:27
90d420e to
d5501b7
Compare
kaxil
reviewed
Sep 30, 2026
kaxil
approved these changes
Sep 30, 2026
Contributor
Backport failed to create: airflow-ctl/v0-1-test. View the failure log Run detailsNote: As of Merging PRs targeted for Airflow 3.X In matter of doubt please ask in #release-management Slack channel.
You can attempt to backport this manually by running: cherry_picker 5e785ac airflow-ctl/v0-1-testThis should apply the commit to the airflow-ctl/v0-1-test branch and leave the commit in conflict state marking After you have resolved the conflicts, you can continue the backport process by running: cherry_picker --continueIf you don't have cherry-picker installed, see the installation guide. |
1 task done
1 task done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Was generative AI tooling used to co-author this PR?
Summary
Clearing a task instance now discards its
task_state_storeentries, so the next attempt starts over instead of resuming from a checkpoint or reconnecting to an external job recorded by the attempt that was cleared.Clearing a task instance now discards its
task_state_storeentries, so the next attempt startsover. Retries are unaffected and still resume.
Why
A retry and a clear were treated identically. Both kept the task's state, both resumed. But they mean different things.
A retry happens because infrastructure failed. Nothing about the work changed, so carrying on from the checkpoint is exactly right, and that is what crash recovery is for. A clear happens because a human intervened, and the usual reason a human clears a task is that something did change: the code, the upstream data, a connection, a config value.
So the behaviour was tuned for the case where nothing changed, and then applied to the case where
something had.
What that cost in practice:
Fixing a bug and clearing left the bug's output in place. A task gets through files 1 to 6, hits bad data on the 7th, you fix the transform and clear. It resumed at 7. Files 1 to 6 still held output from the code you had just fixed, now silently mixed with the corrected work. The task went green, and nothing anywhere said otherwise.
Clearing a succeeded durable task did nothing at all. The operator read back the stored job id, saw the external job had already finished, and returned the stored result in a couple of seconds. This needs no unusual configuration, and there is no reading of "clear" under which doing nothing is what the user asked for.
The two failure modes are asymmetric, which is what decides the default rather than just moving the
problem elsewhere. Discarding when you wanted to resume costs repeated work you can watch happen.
Resuming when you wanted a fresh start produces wrong output you cannot see.
What changed
keep_task_stateonClearTaskInstancesBody, defaulting tofalsepost_clear_task_instances, inside the existingif not dry_run:block andafter
clear_task_instancessucceeds, so a preview discards nothing and a failed clear cannottake the task state with it
_clear_task_state_store_on_successrefactored into a shareddiscard_task_state_storehelper:two callers, two gates, one implementation
existing "Prevent rerun if task is running"
a task is treated the same as a retry"
When to tick the box
Two situations, both documented.
Nothing changed and you only want the task to carry on. Retries normally cover this, so you reach it when retries are exhausted.
An external job is still running. Most operators cancel theirs in
on_kill, so clearing a running task leaves nothing to reconnect to. But clearing a failed task never runson_kill, so a job that outlived its worker is still going, and discarding the stored id submits a second one. Same for operators configured to leave the job alive, such asKubernetesPodOperatorwithon_kill_action="keep_pod".Compatibility
This changes behaviour introduced in 3.3 and released in 3.3.1. Anyone relying on clear-to-resume needs
keep_task_state=true.A single default rather than per-operator behaviour is acceptable precisely because the user keeps an override: if Airflow decided silently per operator, a wrong guess would be unrecoverable, whereas a wrong default is one checkbox.
Tests
Trying to run a dag like this:
This dag showcases some data transformation and mimics a case where bad data came in as
N/Acontrolled by a variable value.So showing it:
First run:
Task state store contains this:
Set the variable rightly now:
airflow variables set handle_missing trueClear with the default:
Next run:
State store:
Now if I cleared by overriding the checkbox for another try (ie: keeping task state):
Observe the logs:
More testing
Tried same test as above from clear from TI page as bulk
Clearing with airflowctl:
Ran this:
{pr_number}.significant.rst, in airflow-core/newsfragments. You can add this file in a follow-up commit after the PR is created so you know the PR number.