Uh oh!
There was an error while loading. Please reload this page.
Add is_backfillable property to DAG API responses - #64644
Conversation
There was a problem hiding this comment.
Pull request overview
This PR improves backfill UX by exposing whether a DAG’s schedule supports backfilling via a new is_backfillable field in DAG API responses, enforcing non-periodic schedule rejection in backfill endpoints, and updating the UI to disable backfill when unsupported.
Changes:
- Add computed
is_backfillableto DAG-related API response models and OpenAPI specs (public + UI). - Validate backfills against
dag.timetable.periodic(rejectingNone,@once,@continuous, asset-triggered, partitioned asset schedules) and rename the related exception. - Update Trigger DAG modal logic and i18n to use
is_backfillable, plus add regression/unit tests.
Reviewed changes
Copilot reviewed 14 out of 15 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
uv.lock | Updates lockfile metadata/deps (includes OAuth/authlib-related changes). |
airflow-ctl/src/airflowctl/api/datamodels/generated.py | Adds is_backfillable to generated CLI client DAG response models. |
airflow-core/src/airflow/api_fastapi/core_api/datamodels/dags.py | Introduces computed is_backfillable on DAGResponse (and inheritors). |
airflow-core/src/airflow/models/backfill.py | Renames schedule exception + switches backfill validation to timetable.periodic. |
airflow-core/src/airflow/api_fastapi/core_api/routes/public/backfills.py | Updates route exception handling to the renamed exception. |
airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml | Publishes is_backfillable in public OpenAPI schema for DAG responses. |
airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yaml | Publishes is_backfillable in private UI OpenAPI schema for DAG responses. |
airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts | Updates generated TS types to include is_backfillable. |
airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts | Updates generated TS schemas to include is_backfillable as required/readOnly. |
airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGModal.tsx | Disables/gates Backfill option using dag.is_backfillable instead of hasSchedule. |
airflow-core/src/airflow/ui/public/i18n/locales/en/components.json | Replaces tooltip string with scheduleNotBackfillable message. |
airflow-core/tests/unit/models/test_backfill.py | Adds coverage for rejecting non-periodic schedules in create/dry-run helpers. |
airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_backfills.py | Updates validation expectations for non-periodic schedules. |
airflow-core/tests/unit/api_fastapi/core_api/datamodels/test_dags.py | Adds unit tests for DAGResponse.is_backfillable computation. |
airflow-core/tests/unit/api_fastapi/core_api/datamodels/__init__.py | Adds package init for new datamodel tests directory. |
Uh oh!
There was an error while loading. Please reload this page.
b45539e to
33e3f8fComparee733faa to
d888c11CompareThere was a problem hiding this comment.
Pull request overview
Copilot reviewed 44 out of 44 changed files in this pull request and generated 4 comments.
Comments suppressed due to low confidence (2)
airflow-core/tests/unit/api_fastapi/core_api/datamodels/test_dags.py:1
DAGResponse.ownersis typed aslist[str](and the OpenAPI/TS types reflect an array). Providing a bare string risks validation failure or unintended coercion (e.g., into a list of characters), making these tests flaky/incorrect. Change the default to a list such as["airflow"].
airflow-core/src/airflow/ui/public/i18n/locales/zh-CN/components.json:1- Many non-English locale files introduce the new
scheduleNotBackfillablemessage in English, which is a localization regression compared to the removed translatedtooltip. Consider translating this new string per locale (or reusing the prior locale-specific tooltip phrasing adapted to the new meaning) so users don’t see English text in localized UIs.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
pierrejeambrun
left a comment
There was a problem hiding this comment.
Looking good overall. Just a few nits and we should be good to merge.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
d888c11 to
27b30a1CompareUh oh!
There was an error while loading. Please reload this page.
The test-to-stable sync (apache#67294) copied airflowctl's generated datamodels from main, so they describe Airflow 3.3's API while this branch ships core 3.2.1. Two consequences, both red once CI started running here: - generate-airflowctl-datamodels regenerates from ../airflow-core/src/airflow/api_fastapi and fails on any drift, so Static checks could never pass - the models required is_backfillable and timetable_periodic, which apache#64644 added in 3.3.0, so every single-object Dag response failed validation against this branch's own PROD image: ValidationError: 2 validation errors for DAGResponse is_backfillable Field required timetable_periodic Field required Run the hook to bring the models back in line with the spec on this branch. This drops 14 model classes that no airflowctl code or test references, plus the 3.3-only fields above. Note RELEASE_NOTES.rst credits "Add ``is_backfillable`` property to DAG API responses (apache#64644)" to airflowctl 0.1.5, but apache#64644 touches only airflow-core -- that line is sync noise, not a client feature.
The test-to-stable sync (apache#67294) copied airflowctl's generated datamodels from main, so they describe Airflow 3.3's API while this branch ships core 3.2.1. Two consequences, both red once CI started running here: - generate-airflowctl-datamodels regenerates from ../airflow-core/src/airflow/api_fastapi and fails on any drift, so Static checks could never pass - the models required is_backfillable and timetable_periodic, which apache#64644 added in 3.3.0, so every single-object Dag response failed validation against this branch's own PROD image: ValidationError: 2 validation errors for DAGResponse is_backfillable Field required timetable_periodic Field required Run the hook to bring the models back in line with the spec on this branch. This drops 14 model classes that no airflowctl code or test references, plus the 3.3-only fields above. Note RELEASE_NOTES.rst credits "Add ``is_backfillable`` property to DAG API responses (apache#64644)" to airflowctl 0.1.5, but apache#64644 touches only airflow-core -- that line is sync noise, not a client feature.
Context
Currently, when attempting to backfill a DAG that has an Asset schedule, after going to the backfill section in the trigger form and choosing dates we get an error saying: "No runs matching selected criteria." (on 2.11 it says "No run dates were found for the given dates and dag interval."). This is confusing UX-wise: instead of being shown right from the start (because it is tied to how the DAG is configured), it appears only after the user selects a date range. This sequence of events implies causality between the user's choice and the error — which is not true.
Additionally, DAGs that configure
allowed_run_typesto excludeBACKFILL_JOBhad no upfront indication that backfilling is disabled.Summary
timetable_periodicboolean column toDagModelvia Alembic migration (following thetimetable_partitionedpattern), set fromdag.timetable.periodicduring DAG sync.is_backfillablefield to DAG API responses that unifies both schedule compatibility (timetable_periodic) and run-type permissions (allowed_run_types) into a single source of truth.timetable_summary == "None"check with a propertimetable.periodiccheck in both_do_dry_runand_create_backfill, catching all non-periodic schedules (@once,@continuous, asset-triggered, partitioned asset) — not just unscheduled DAGs.allowed_run_typesvalidation to_do_dry_run(previously only in_create_backfill), ensuring dry-run and create return consistent errors.DagNoScheduleExceptiontoDagNonPeriodicScheduleExceptionto reflect the broader validation.is_backfillablefield instead of thehasScheduleheuristic, so the Backfill option is correctly disabled for all non-backfillable DAGs.Changes
Migration:
timetable_periodicBoolean column to thedagtable (server_default="0",nullable=False).dag_processing/collection.pysetsdm.timetable_periodic = dag.timetable.periodicduring DAG sync.API / Models:
DagModeldeclarestimetable_periodic: Mapped[bool].DAGResponse.is_backfillable— computed field:Trueonly whentimetable_periodic is TrueANDBACKFILL_JOBis permitted byallowed_run_types.backfill.py— both_create_backfilland_do_dry_runcheckdag.timetable.periodicandallowed_run_types.DagNoScheduleException->DagNonPeriodicScheduleException.dag_command.py—is_backfillablecomputed from bothperiodicandallowed_run_types.UI:
TriggerDAGModal.tsxusesis_backfillableto gate the Backfill radio option.hasScheduleis kept forTriggerDAGForm(controls data interval display — separate concern).backfill.tooltiptobackfill.scheduleNotBackfillablein all 21 locales).Tests:
TestIsBackfillabletests covering: non-periodic, periodic,allowed_run_types=None, backfill included/excluded, and the combined non-periodic+allowed case.test_create_backfill_non_periodic_schedule_rejectedandtest_do_dry_run_non_periodic_schedule_rejectedtests covering@once,@continuous,None, and asset schedules.test_no_schedule_dagfor new exception behavior.Was generative AI tooling used to co-author this PR?
Generated-by: Claude Opus 4.6 following the guidelines
{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.