Skip to content

wait_for_past_depends_before_skipping does not seem to have any effect #55146

Open

Description

@matthieucx

Apache Airflow version

Airflow 3.1.0

What happened?

I am part of a data engineering team. We use airflow to orchestrate our data ingestion pipelines. At a high-level, they are made of:

  • An ingestion task group, that moves data from a source system to our S3 storage
  • Validation tests
  • Processing jobs that clean up and prepares the data for use by downstream consumers
  • Validations tests on the processed data

The processing jobs run in Spark. To avoid overhead, I have been looking at using Airflow's skipping mechanisms to skip the rest of the pipeline if there is no data to be ingested.

However, we need the processing jobs to run sequentially. For this purpose, we use depends_on_past. I then stumbled upon the PR introducing wait_for_past_depends_before_skipping, which seems like it would allow me to skip tasks while still preserving the dependencies on past runs. However, the flag does not seem to have an effect.

What you think should happen instead?

The flag should behave as advertised in the base PR and in the docs.

How to reproduce

from airflow import DAG
from airflow.models import Param
from airflow.providers.standard.operators.empty import EmptyOperator
from airflow.providers.standard.operators.python import ShortCircuitOperator
from airflow.sdk import get_current_context


def check_continue():
    ctx = get_current_context()
    skip_downstream = ctx["params"]["skip"]
    return not skip_downstream


with DAG(
    dag_id="test_airflow_skip",
    schedule=None,
    params={
        "skip": Param(default=False, type="boolean"),
    },
) as dag:
    depends_on_past = EmptyOperator(
        task_id="depends_on_past",
        depends_on_past=True,
        wait_for_past_depends_before_skipping=True,
    )
    skip = ShortCircuitOperator(
        task_id="skip",
        python_callable=check_continue,
    )

    skip >> depends_on_past
  1. Launch a run
  2. Then manually set the state of the depends_on_past task to failed
  3. Then launch a run with the skip parameter enabled: depends_on_past will be skipped when it shouldn't be.
Image

Operating System

Ubuntu 22.04.5 LTS

Versions of Apache Airflow Providers

No response

Deployment

Docker-Compose

Deployment details

No response

Anything else?

No response

Are you willing to submit PR?

  • Yes I am willing to submit a PR!

Code of Conduct

Activity

  1. Brunda10 commented on Sep 3, 2025

    @Brunda10
    Contributor

    I would like to work on this issue -Please assign it to me if nobody else is already working on it?

  2. eladkal commented on Sep 3, 2025

    @eladkal
    Contributor
  3. matthieucx commented on Oct 3, 2025

    @matthieucx
    Author

    @eladkal @hussein-awala Hello! I just tested this in an airflow 3.1.0 standalone setup, this issue does affect the latest version. I updated the issue description to reflect this and further streamlined the reproduction example.

  4. matthieucx commented on Nov 19, 2025

    @matthieucx
    Author

    @eladkal @hussein-awala Hello! Sorry for the repeated pings. Would it be possible to triage the issue, as I managed to reproduce it after the latest minor airflow update?

  5. Tomi-1997 commented on Mar 11, 2026

    @Tomi-1997
    Contributor

    Hey, I think I achieved the effect you wanted with these changes

    • I set the dependent task to have a trigger rule to run if none tasks failed
    • The short circuit to respect downstream trigger rules

    Also, If the dependent task is a direct child, it will be skipped- so I added an empty task to bridge between them.
    This is my result:
    Image

    Here's the changes, let me know what you think

    from airflow import DAG
    from airflow.models import Param
    from airflow.providers.standard.operators.empty import EmptyOperator
    from airflow.providers.standard.operators.python import ShortCircuitOperator
    from airflow.providers.standard.operators.bash import BashOperator
    from airflow.sdk import get_current_context
    from airflow.utils.trigger_rule import TriggerRule
    
    
    def check_continue():
        ctx = get_current_context()
        skip_downstream = ctx["params"]["skip"]
        return not skip_downstream
    
    
    with DAG(
        dag_id="test_airflow_skip",
        schedule=None,
        params={
            "skip": Param(default=False, type="boolean"),
        },
    ) as dag:
        depends_on_past = EmptyOperator(
            task_id="depends_on_past",
            depends_on_past=True,
            wait_for_past_depends_before_skipping=True,
            trigger_rule=TriggerRule.NONE_FAILED,
        )
    
        bridge = EmptyOperator(
            task_id="bridge",
        )
    
        skip = ShortCircuitOperator(
            task_id="skip",
            python_callable=check_continue,
            ignore_downstream_trigger_rules=False,
        )
    
        skip >> bridge >> depends_on_past
  6. luc-pimentel commented on Oct 19, 2026

    @luc-pimentel
    Contributor

    Reproduced on 3.3.2 with airflow standalone on SQLite: ShortCircuitOperator >> PythonOperator(depends_on_past=True, wait_for_past_depends_before_skipping=True), run 1 fails the downstream task, run 2 short-circuits.

    Dag Run 1 Run 2 after 60 s
    flag on depends_on_past=failed depends_on_past=skipped (expected None, waiting)
    flag off (control) depends_on_past=failed depends_on_past=skipped

    The cause is in two places: SkipMixin.skip in the task SDK skips every direct downstream task through the execution API before any scheduler dependency runs, and the deps only read the flag from the DepContext, which nothing sets in Airflow 3.

    Fix in #75028.


    Drafted-by: Claude Code (Fable 5.1); reviewed by @luc-pimentel before posting

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:corekind:bugThis is a clearly a bugneeds-triagelabel for new issues that we didn't triage yet

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions