Skip to content

Running tasks marked as skipped on DagRun timeout #30264

Open

Description

@erdos2n

Apache Airflow version

2.5.2

What happened

Users are experiencing the following:

  • A DAG begins to run
  • Task(s) go into running state, as expected
  • The DagRun times out, marking any currently running task as SKIPPED
  • Because tasks are not mark as failed the on_failure_callback never gets revoked

Here are some example logs:

[2023-03-22, 16:30:02 PDT] {local_task_job.py:266} WARNING - DagRun timed out after 4:00:02.394287.
[2023-03-22, 16:30:07 PDT] {local_task_job.py:266} WARNING - DagRun timed out after 4:00:07.447373.
[2023-03-22, 16:30:07 PDT] {local_task_job.py:272} WARNING - State of this instance has been externally set to skipped. Terminating instance.
[2023-03-22, 16:30:07 PDT] {process_utils.py:129} INFO - Sending Signals.SIGTERM to group 8515. PIDs of all processes in the group: [8515]

What you think should happen instead

Once a DagRun times out, tasks that are currently in RUNNING should be marked as FAILED and downstream tasks should be marked as UPSTREAM_FAILED

How to reproduce

The following DAG will cause this intermittently

import time
import logging

from airflow.decorators import dag, task
from airflow.utils.dates import datetime, timedelta



@task
def task_1():
    import random
    pulses = random.randint(5, 10)
    for i in range(pulses):
        logging.info(f"pulsing: pulse...{i}")
        time.sleep(4)


@task
def task_2():
    import random
    pulses = random.randint(10, 20)
    for i in range(pulses):
        logging.info(f"pulsing: pulse...{i}")
        time.sleep(5)

@task
def downstream_finished_task():
    logging.info("task finished")
    time.sleep(20)

@dag(dag_id="dagrun_interval_test",
     schedule_interval="*/5 * * * *",
     start_date=datetime(2023, 3, 23),
     dagrun_timeout=timedelta(seconds=30),
     catchup=False)
def my_dag():
    return [task_1(), task_2()] >> downstream_finished_task()


dag = my_dag()
  • Running tasks marked skipped
  • Downstream left with no status

See screenshot
Screen Shot 2023-03-23 at 4 23 34 PM

Operating System

MacOS

Versions of Apache Airflow Providers

N/A

Deployment

Astronomer

Deployment details

Airflow Version 2.5.2

Anything else

Every time a DagRun times out

Are you willing to submit PR?

  • Yes I am willing to submit a PR!

Code of Conduct

Activity

  1. eladkal commented on Mar 23, 2023

    @eladkal
    Contributor

    The dag timeouted so the dag status is marked as failed.
    Tasks did not finish so why should they be set to fail?

    if (
    dag_run.start_date
    and dag.dagrun_timeout
    and dag_run.start_date < timezone.utcnow() - dag.dagrun_timeout
    ):
    dag_run.set_state(DagRunState.FAILED)
    unfinished_task_instances = (
    session.query(TI)
    .filter(TI.dag_id == dag_run.dag_id)
    .filter(TI.run_id == dag_run.run_id)
    .filter(TI.state.in_(State.unfinished))
    )
    for task_instance in unfinished_task_instances:
    task_instance.state = TaskInstanceState.SKIPPED

  2. erdos2n commented on Mar 24, 2023

    @erdos2n
    ContributorAuthor

    @eladkal Maybe they should not be set to fail, but they should also not be set to skipped. The task was not skipped, technically speaking.

    An issue that has come up is that a user wants an alert for a specific task failure, so they don't want to set the on_failure_callback on the dag level. That specific task gets marked skipped on a dagrun_timeout and the on_failure_callback isn't triggered.

    I believe it's worth discussing either marking these tasks that are stopped mid-run as FAILED or introducing a new state into the task instance.

    I'm curious if SHUTDOWN makes more sense in this instance. It seems to fit what is occurring more than skipped.

    SHUTDOWN # External request to shut down (e.g. marked failed when running)
    

    https://github.com/apache/airflow/blob/main/airflow/utils/state.py#L42

    Thoughts?

  3. wolfier commented on Mar 24, 2023

    @wolfier
    Contributor

    Instead of setting the state to SKIPPED, I propose calling handle_failure such that the callbacks are executed.

  4. erdos2n commented on Mar 24, 2023

    @erdos2n
    ContributorAuthor

    Hey Alan, did more digging. handle_failure is only called on failures, which means that my initial proposal of SHUTDOWN would not work, anyways. But if the remaining tasks are marked as upstream_failed then they would trigger the handle_failure callback.

    So in short, adding the handle_failure callback would work, or marking downstream tasks as upstream_failed would work. Thoughts?

  5. eladkal commented on Mar 24, 2023

    @eladkal
    Contributor

    Just to clarify if the goal is to change the current behavior from skipped to fail this is a breaking change and can not happen before Airflow 3.

    Before discussing how to get it done I suggest first to discuss if this should be done. I'm not convinced setting tasks to failure when dag timeout is the desired behavior.

  6. erdos2n commented on Mar 24, 2023

    @erdos2n
    ContributorAuthor

    The goal is to change the behavior, but not necessarily from skipped to fail, just something to trigger the handle_failure method so callbacks can exhibit (more) expected behavior from users.

  7. hussein-awala commented on Mar 25, 2023

    @hussein-awala
    Member

    The goal is to change the behavior, but not necessarily from skipped to fail, just something to trigger the handle_failure method so callbacks can exhibit (more) expected behavior from users.

    Since the task didn't fail, I don't see the need to run the failure callback in every stopped task, the dag failure callback is enough to handle this case, where we can check if the run failed due to timeout, and select skipped tasks in metadata to do what we need to do. WDYT?

  8. erdos2n commented on Mar 25, 2023

    @erdos2n
    ContributorAuthor

    Well this user wants a callback if this specific task fails, so not on the dag level. Could be that we need a on skipped callback. Thoughts?

  9. eladkal commented on Apr 12, 2023

    @eladkal
    Contributor

    Well this user wants a callback if this specific task fails, so not on the dag level. Could be that we need a on skipped callback. Thoughts?

    I'm OK with adding on_skipped_callback (regardless of what we discuss here, this is probably something we should add)

  10. eladkal commented on Apr 27, 2023

    @eladkal
    Contributor

    Should we scope this issue to adding on_skipped_callback ?
    @erdos2n is that a suitable solution for your use case?

  11. pankajkoti commented on Jul 21, 2023

    @pankajkoti
    Member

    @erdos2n would you have an update on the last question from Elad?

  12. 34 remaining items

  13. added
    staleStale PRs per the .github/workflows/stale.yml policy file
    on Dec 12, 2024
  14. raphaelauv commented on Dec 12, 2024

    @raphaelauv
    Contributor

    No stale

  15. removed
    staleStale PRs per the .github/workflows/stale.yml policy file
    on Dec 13, 2024
  16. CyberDuck79 commented on Dec 18, 2024

    @CyberDuck79

    I agree that this should be reopened. IMO skipped has ne sense for the task instance state, as it was running but was terminating before it ends cause of the dag run timeout. Beside that, we try a workaround using the 'on_skipped_callback' to set the TI state to failed, but it seems that the callback is not executed in that scenario (airflow 2.9.3). Does someone knows why ? Thanks

    We are running into the same issue too. In our case, we have our dags timeout, which can cause some tasks to skip while running; these finish with this:

    [2024-11-22, 20:27:36 UTC] {taskinstance.py:3092} ERROR - Received SIGTERM. Terminating subprocesses.

    We believe this means that AirflowSkipException is not being raised, so on_skip_callback will not run at all. In order to actually call on_skipped_callback, something would need to specifically raise AirflowSkipException.

    Can anyone else confirm if our understanding is correct? At the end of the day, we would like a way to have `on_kill' callback function that sends out an email if any task is killed

    Same behavior for us on MWAA; tasks are killed by SIGTERM. Could it launch any callback? The skipped callback was not configured in our case.
    We discovered this behavior accidentally due to a bad configuration, but it raised 3 questions:

    • Is the SIGTERM normal behavior?
    • Is skipped state the best state for that case?
    • I suspected it, but are there no DAG-level callbacks?

    For the DAG-level callbacks, it's not the first time we have encountered an issue with our alerting system because tasks were killed (but it was due to the MWAA Airflow internal architecture). So, it could be a good feature, even if I think it is out of the scope of this issue.

  17. CyberDuck79 commented on Dec 18, 2024

    @CyberDuck79

    Well, after experimentation, it seems there is confusion about callback configurations.
    There is DAG level callbacks: #38897
    But we were also confused by the configurations:

    • In the DAG config in default_args (our old way of configuring callbacks) -> it configures the callbacks at the task level for all tasks.
    • In the DAG config directly (on_failure_callback, for example) -> callback triggered at dag level by dag state (so in case of dag run timeout, failed state -> failure callback)
      The second configuration would allow the callback to be triggered even if the task process is killed.

    For the question of the skipped status:
    Maybe the skipped status is not very clear because the task could have already started, but this information is included in the skipped callback so the DAG run timeout case can be handled. It seems that in Airflow, the meaning of the skipped state includes unfinished tasks.
    An unfinished state could be more clear, but is it worse to add a new state to handle?

    In regard to these discoveries, I think the issue should be closed because there is nothing that cannot be handled, and a conversation about a possible new "unfinished" state for those who find it interesting should be initiated.
    I hope my comments could help to clarify the confusions that I read in this conversation.

  18. morooshka commented on Jan 16, 2025

    @morooshka
    Contributor

    Also faced this. I see there one confusion - we fail the task on execution timeout but not fail on DAG timeout. To my mind the behaviour should be similar - fail the task

    P.S. In which case one should need to skip the task if the whole DAG times out?

  19. AlvaroCavalcante commented on Feb 11, 2025

    @AlvaroCavalcante

    I was facing this issue, but I was able to call the on_failure_callback when I set this callback in the DAG definition, as stated here: https://stackoverflow.com/questions/69312630/airflow-triggering-the-on-failure-callback-when-the-dagrun-timeout-is-exceed

  20. github-actions commented on Feb 11, 2026

    @github-actions
    Contributor

    This issue has been automatically marked as stale because it has been open for 365 days without any activity. There has been several Airflow releases since last activity on this issue. Kindly asking to recheck the report against latest Airflow version and let us know if the issue is reproducible. The issue will be closed in next 30 days if no further activity occurs from the issue author.

  21. morooshka commented on Feb 11, 2026

    @morooshka
    Contributor

    @AlvaroCavalcante I would prefer to have the default on_failure_callback called here without additional efforts. Wouldn't it be more clear here?

  22. removed
    needs-triagelabel for new issues that we didn't triage yet
    on Feb 12, 2026
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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions