You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add "Mark as Skipped" action for Task Instances in the Airflow 3 UI #72386
The Airflow 3 UI currently allows operators to manually mark a Task Instance as success or failed, but does not provide an option to mark it as skipped.
Use case/motivation
In the Airflow 3 UI, the Task Instance "Mark as" action only exposes:
Success
Failed
As a result, SKIPPED is not available as a manual Task Instance action.
Expected behavior
The Task Instance "Mark as" action should provide:
Success
Failed
Skipped
Selecting Skipped should set the selected Task Instance(s) to TaskInstanceState.SKIPPED, without executing the task.
Use case
During the manual recovery of a DAG run, an operator may decide that a particular task should not be executed for this run.
For example:
task_a → task_b → task_c
If task_b should intentionally not run for this particular DAG run, the desired result is:
task_a → SUCCESS
task_b → SKIPPED
task_c → ...
Marking task_b as SUCCESS is not equivalent.
SUCCESS means that the task successfully executed, whereas SKIPPED records that the task was intentionally not executed.
This distinction is important for:
accurately representing the execution history;
operational troubleshooting
downstream trigger_rule evaluation
depends_on_past
Airflow's documentation explicitly treats skipped differently from success. For example, none_failed considers upstream tasks that are either successful or skipped as acceptable, while none_skipped explicitly rejects skipped upstream tasks. Therefore, replacing SKIPPED with SUCCESS can change DAG behavior.
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.
Wait help me understand the reasoning here. Is "Mark as skipped" only relevant when the dag is running and you want to mark it as skipped before the scheduler tries to run it? I am wary about marking existing task instances as skipped after the fact.
My main use case is when the DAG run is still in progress and is blocked waiting for an input that we already know will never arrive.
For example, imagine a DAG that processes a set of input files:
file_A → ingestion_A ┐
file_B → ingestion_B ├→ transformations → ...
file_C → ingestion_C ┘
The DAG is currently waiting for "file_B" to arrive.
Now imagine a production incident has occurred and we know that "file_B" will not be delivered for this particular run.
As an operator, I would like to be able to manually mark "ingestion_B" as "SKIPPED" so that the DAG can continue:
ingestion_A → SUCCESS
ingestion_B → SKIPPED ← manually bypassed
ingestion_C → SUCCESS
↓
transformations
The important point is that I don't want to mark the task as "SUCCESS", because that would incorrectly indicate that the ingestion actually took place.
I also don't want to simply clear/remove the task instance, because I want the execution history to retain the information that this particular input was intentionally bypassed as part of the incident recovery.
So the use case is essentially:
DAG run is active and waiting for an input.
A production incident makes it known that the input will never arrive.
The operator manually marks the corresponding task as "SKIPPED".
The DAG can proceed according to its normal dependency/trigger-rule semantics.
The Airflow UI/history clearly shows that this task was intentionally skipped rather than successfully executed.
I agree that marking an already completed task as "SKIPPED" after the fact would be a different use case, and I don't think that is particularly useful.
Okay so we should definitely only allow task instances with a pending state to be marked as skipped.
Other than having to edit the dag code, why not add AirflowSkipException? Then the dag author is the one determining if skipped is appropriate (has work already been done?) vs a possibly different user later.
I see value in allowing manually set of task as skipped.
This is helpful for incident recovery:
When the logic fixed externally to Airflow and you want to specify the task didn't run but also doesn't need to run.
When you have downstream task which depends on current task to be finished as skip and you don't want to run it but just mark it as so. This is very relevant for use cases where you develop locally more tasks/branches.
@eladkal I agree in general, but the main issue with this is that you need to "pre-support" this in the Dag, as by default skipping a task, ingestion_B in this example, wouldn't allow transformations to run as the default trigger rule is ALL_SUCCESS. This could possibly even lead to the whole run being marked as failed/"deadlocked".
Which equates to severely limiting the usefulness of it.
@eladkal I agree in general, but the main issue with this is that you need to "pre-support" this in the Dag, as by default skipping a task, ingestion_B in this example, wouldn't allow transformations to run as the default trigger rule is ALL_SUCCESS. This could possibly even lead to the whole run being marked as failed/"deadlocked".
Which equates to severely limiting the usefulness of it.
That may be but the request to add mark as skipped is valid. I agree that there are use cases where missuse of the capability can lead to undesired outcome but that is true for many features. When users take manual actions on the UI it means they also tracking it so if they decided wrong they can fix it.
I agree with this point. Mark as Skipped should not bypass or override the DAG's existing dependency and trigger_rule semantics.
The purpose of the feature is simply to let an operator say: "This pending task must not run for this particular DAG run."
What happens downstream should remain entirely governed by the DAG definition.
If the DAG is designed to tolerate a skipped task, the run can continue. If it requires ALL_SUCCESS, then the downstream task should remain blocked - which is the expected behavior.
The important part for me is that we can record the operational decision as SKIPPED rather than incorrectly marking the task as SUCCESS.
And I agree that this should only be allowed for Task Instances that have not started running yet.
Activity
boring-cyborg commentedon Sep 1, 2026
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.
bbovenzi commentedon Sep 23, 2026
Wait help me understand the reasoning here. Is "Mark as skipped" only relevant when the dag is running and you want to mark it as skipped before the scheduler tries to run it? I am wary about marking existing task instances as skipped after the fact.
Antalares commentedon Sep 24, 2026
My main use case is when the DAG run is still in progress and is blocked waiting for an input that we already know will never arrive.
For example, imagine a DAG that processes a set of input files:
file_A → ingestion_A ┐
file_B → ingestion_B ├→ transformations → ...
file_C → ingestion_C ┘
The DAG is currently waiting for "file_B" to arrive.
Now imagine a production incident has occurred and we know that "file_B" will not be delivered for this particular run.
As an operator, I would like to be able to manually mark "ingestion_B" as "SKIPPED" so that the DAG can continue:
ingestion_A → SUCCESS
ingestion_B → SKIPPED ← manually bypassed
ingestion_C → SUCCESS
↓
transformations
The important point is that I don't want to mark the task as "SUCCESS", because that would incorrectly indicate that the ingestion actually took place.
I also don't want to simply clear/remove the task instance, because I want the execution history to retain the information that this particular input was intentionally bypassed as part of the incident recovery.
So the use case is essentially:
I agree that marking an already completed task as "SKIPPED" after the fact would be a different use case, and I don't think that is particularly useful.
bbovenzi commentedon Sep 29, 2026
Okay so we should definitely only allow task instances with a pending state to be marked as skipped.
Other than having to edit the dag code, why not add
AirflowSkipException? Then the dag author is the one determining if skipped is appropriate (has work already been done?) vs a possibly different user later.ashb commentedon Sep 29, 2026
In this example case
file_Bis running. What state should it be put to? How?eladkal commentedon Sep 30, 2026
I see value in allowing manually set of task as skipped.
This is helpful for incident recovery:
ashb commentedon Sep 30, 2026
@eladkal I agree in general, but the main issue with this is that you need to "pre-support" this in the Dag, as by default skipping a task,
ingestion_Bin this example, wouldn't allowtransformationsto run as the default trigger rule is ALL_SUCCESS. This could possibly even lead to the whole run being marked as failed/"deadlocked".Which equates to severely limiting the usefulness of it.
eladkal commentedon Sep 30, 2026
That may be but the request to add mark as skipped is valid. I agree that there are use cases where missuse of the capability can lead to undesired outcome but that is true for many features. When users take manual actions on the UI it means they also tracking it so if they decided wrong they can fix it.
Antalares commentedon Sep 30, 2026
I agree with this point. Mark as Skipped should not bypass or override the DAG's existing dependency and trigger_rule semantics.
The purpose of the feature is simply to let an operator say: "This pending task must not run for this particular DAG run."
What happens downstream should remain entirely governed by the DAG definition.
If the DAG is designed to tolerate a skipped task, the run can continue. If it requires ALL_SUCCESS, then the downstream task should remain blocked - which is the expected behavior.
The important part for me is that we can record the operational decision as SKIPPED rather than incorrectly marking the task as SUCCESS.
And I agree that this should only be allowed for Task Instances that have not started running yet.
ashb commentedon Sep 30, 2026
As long as we document this behaviour/gotchas then this sounds good to me.