Skip to content

Ignore task start_date and end_date on manual runs - #71758

Closed
yuseok89 wants to merge 4 commits into
apache:mainfrom
yuseok89:fix-manual-dagrun-outside-task-date-window
Closed

yuseok89 wants to merge 4 commits into
apache:mainfrom
yuseok89:fix-manual-dagrun-outside-task-date-window

Conversation

@yuseok89

@yuseok89 yuseok89 commented Aug 18, 2026 •

Copy link
Copy Markdown
Contributor

closes: #38513

A manual run whose logical date falls outside a task's start_date / end_date window creates no task instance for that task. When every task is filtered out this way, the run ends up with no task instances at all and is immediately reported as success, with no error and no failed task to alert on. Manual runs are now exempt from that window, as backfill runs already are.

The issue has been assigned since 2024 with no activity, happy to hand it back.

Verified in the UI

Using a Dag modelled on the one from the issue, with a start_date of 2050 and three chained @task functions (extract → transform → load).

Before

Screen.Recording.2026-08-18.at.11.19.52.PM.mov

After

Screen.Recording.2026-08-18.at.11.24.09.PM.mov

Was generative AI tooling used to co-author this PR?
  • Yes (please specify the tool below)
    • Opus 5

  • Read the Pull Request Guidelines for more information. Note: commit author/co-author name and email in commits become permanently public when merged.
  • For fundamental code changes, an Airflow Improvement Proposal (AIP) is needed.
  • When adding dependency, check compliance with the ASF 3rd Party License Policy.
  • For significant user-facing changes create newsfragment: {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.

@raphaelauv

Copy link
Copy Markdown
Contributor

manual run whose logical date is outside the task date window must still run the tasks

why do you think this ?

If you want to detect the case of a dag_run that did not run any task then add a very last task

from airflow.providers.standard.operators.empty import EmptyOperator
from airflow.providers.standard.operators.python import PythonOperator
from airflow.sdk import TaskInstanceState, TriggerRule, get_current_context
from airflow.sdk import DAG, CronDataIntervalTimetable, timezone

with DAG(
    dag_id="test_dag_run",
    schedule=CronDataIntervalTimetable("0 0 1 * *", "Europe/Paris"),
    start_date=timezone.parse("2026-07-05T00:00:00", "Europe/Paris"),
    catchup=False,
):
    task_1 = EmptyOperator(
        task_id="Empty",
    )


    def final_status_callable():
        context = get_current_context()
        ti = context["ti"]
        dag_run = context["dag_run"]

        states_by_run = ti.get_task_states(
            dag_id=ti.dag_id,
            run_ids=[dag_run.run_id],
        )
        task_states = states_by_run.get(dag_run.run_id, {})

        print(f"Status of all tasks for dag_run {dag_run.run_id!r}:")
        failed_tasks = []
        all_tasks = []
        for task_id, state in sorted(task_states.items()):
            if task_id == ti.task_id:
                continue  # this task itself is still "running"
            print(f"  {task_id:<30} {state}")
            all_tasks.append(task_id)
            if state in (TaskInstanceState.FAILED, TaskInstanceState.UPSTREAM_FAILED):
                failed_tasks.append(task_id)

        if failed_tasks:
            raise RuntimeError(f"These tasks did not succeed: {failed_tasks}")

        if len(all_tasks) == 0:
            raise RuntimeError(f"Zero tasks run")

    task_2 = final_status = PythonOperator(
        task_id="final_status",
        python_callable=final_status_callable,
        trigger_rule=TriggerRule.ALL_DONE,
    )

    task_1 >> task_2

@yuseok89

Copy link
Copy Markdown
Contributor Author

@raphaelauv
Thanks for taking a look!
Have you had a chance to look at the original issue (#38513)? My implementation followed the direction discussed there, which I understood as treating this as a bug and fixing it so a manual run actually executes its tasks. There's some context in that thread on the reasoning, in case it's useful.
That said, if you think it's better to keep the date-window semantics for manual runs and only fix the part where an empty run gets reported as success, I'd be glad to discuss that here.

@raphaelauv

raphaelauv commented Aug 18, 2026 •

Copy link
Copy Markdown
Contributor

empty run gets reported as success sounds correct to me since nothing fail

what I would prefer is the option to mark skipped tasks that have out of date start_date or end_date

and then if you need run a PythonOperator that check that all task where skipped

@yuseok89
yuseok89 marked this pull request as ready for review August 19, 2026 06:55
@yuseok89
yuseok89 requested review from XD-DENG and ashb as code owners August 19, 2026 06:55
@yuseok89

Copy link
Copy Markdown
Contributor Author

@raphaelauv

You have a point that nothing actually failed there, and marking the tasks as skipped would certainly read better than today's empty grid.

What tips it for me is an inconsistency that already exists between backfill and manual runs. On a Dag whose start_date is 2050, a backfill over 2026-05-01 to 2026-05-03 runs those tasks to completion. Creating a backfill does not check the Dag's start_date at all, and backfill runs are already exempt from this task date filter. A manual run at the very same logical date produces a run with no task instances at all. The only thing separating the two is the run_type label on otherwise identical work.

So the date window is not really a rule about whether these tasks may run at that logical date. It is a rule about what the scheduler creates, which is also how the docs describe start_date.

Did you try your snippet with the start_date moved to 2050? I did, and final_status gets no task instance either, so the check never runs and there is nothing left to detect the empty run with.

@raphaelauv

Copy link
Copy Markdown
Contributor

Okay, it makes sense to make the behavior of 'backfill' and 'manual trigger' equivalent. In that case, could you add to the documentation that start_date and end_date on tasks are ignored in the event of a manual trigger?

And also update the BaseOperator doc to state that these settings are only taken into account for scheduled runs, and not for manual or backfill runs.

Yes my example do not works with tasks that are not run by the scheduler

@yuseok89

Copy link
Copy Markdown
Contributor Author

Done. Thanks for pushing on this, the semantics are better documented now than before the discussion.

@raphaelauv

Copy link
Copy Markdown
Contributor

@raphaelauv

Copy link
Copy Markdown
Contributor

could you also rename your pr somrhing like

ignore tasks start_date and end_date on manual trigger

@yuseok89 yuseok89 changed the title Fix manual Dag runs reporting success without running any task Ignore task start_date and end_date on manual runs Aug 19, 2026
@yuseok89

Copy link
Copy Markdown
Contributor Author

Both done. Thanks for pushing on this, the PR ended up better than where it started.

@raphaelauv

Copy link
Copy Markdown
Contributor

gentle ping @amoghrajesh , thanks

@potiuk

potiuk commented Sep 25, 2026

Copy link
Copy Markdown
Member

Hello @yuseok89 - thank you for your contributions to Apache Airflow!

The Airflow community has introduced a limit of 5 open pull requests at a time for contributors without write access to the repository. You currently have 11 open pull requests, so - as a one-time step of introducing the limit - we closed the ones where maintainers have not engaged yet:

These pull requests stay open because maintainers are already engaged in them - they count towards your limit:

This is not a judgement of you or of your changes. We never told contributors before that opening many pull requests at once was a problem, so there is nothing to feel bad about - and nothing is lost: your branches, commits and the review history stay where they are.

What we ask you to do is to make your first prioritization decision: choose which of the pull requests above matter most to you, and reopen them (up to 5 open at a time, including the ones still open) with the "Reopen pull request" button or gh pr reopen <PR_NUMBER> --repo apache/airflow. Reopen the ones you are ready to follow through - keep them rebased, respond to review comments and fix failing checks.

While your pull requests are waiting for review, the most valuable thing you can do is help in other ways - reviewing other contributors' pull requests, helping with issues, and taking part in the discussions on the devlist and Slack.

Why we introduced the limit, what it means for you and how to reopen or restore a pull request is explained in https://github.com/apache/airflow/blob/main/contributing-docs/32_open_pull_request_limit.rst.


Drafted-by: Claude Code (Opus 5); reviewed by @potiuk before posting

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

Labels

closed because of open PR limit Closed as a one-time step of introducing the open pull request limit

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DAGs with future start_date are automatically marked as success without executing tasks

3 participants