Add is_backfillable property to DAG API responses - #64644

Merged
pierrejeambrun merged 1 commit into
apache:mainfrom
Dev-iL:2604/invalid_schedule
Apr 14, 2026
Merged

Add is_backfillable property to DAG API responses#64644
pierrejeambrun merged 1 commit into
apache:mainfrom
Dev-iL:2604/invalid_schedule

Conversation

@Dev-iL

@Dev-iLDev-iL commented Apr 2, 2026

Copy link
Copy Markdown
Collaborator

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_types to exclude BACKFILL_JOB had no upfront indication that backfilling is disabled.

Summary

  • Adds a timetable_periodic boolean column to DagModel via Alembic migration (following the timetable_partitioned pattern), set from dag.timetable.periodic during DAG sync.
  • Adds a computed is_backfillable field to DAG API responses that unifies both schedule compatibility (timetable_periodic) and run-type permissions (allowed_run_types) into a single source of truth.
  • Replaces the backend's string-based timetable_summary == "None" check with a proper timetable.periodic check in both _do_dry_run and _create_backfill, catching all non-periodic schedules (@once, @continuous, asset-triggered, partitioned asset) — not just unscheduled DAGs.
  • Adds allowed_run_types validation to _do_dry_run (previously only in _create_backfill), ensuring dry-run and create return consistent errors.
  • Renames DagNoScheduleException to DagNonPeriodicScheduleException to reflect the broader validation.
  • Updates the UI to use the new is_backfillable field instead of the hasSchedule heuristic, so the Backfill option is correctly disabled for all non-backfillable DAGs.
image

Changes

Migration:

  • Migration 0111 adds timetable_periodic Boolean column to the dag table (server_default="0", nullable=False).
  • dag_processing/collection.py sets dm.timetable_periodic = dag.timetable.periodic during DAG sync.

API / Models:

  • DagModel declares timetable_periodic: Mapped[bool].
  • DAGResponse.is_backfillable — computed field: True only when timetable_periodic is True AND BACKFILL_JOB is permitted by allowed_run_types.
  • backfill.py — both _create_backfill and _do_dry_run check dag.timetable.periodic and allowed_run_types.
  • Renamed DagNoScheduleException -> DagNonPeriodicScheduleException.
  • dag_command.pyis_backfillable computed from both periodic and allowed_run_types.

UI:

  • TriggerDAGModal.tsx uses is_backfillable to gate the Backfill radio option. hasSchedule is kept for TriggerDAGForm (controls data interval display — separate concern).
  • Updated i18n strings (renamed backfill.tooltip to backfill.scheduleNotBackfillable in all 21 locales).

Tests:

  • New TestIsBackfillable tests covering: non-periodic, periodic, allowed_run_types=None, backfill included/excluded, and the combined non-periodic+allowed case.
  • New test_create_backfill_non_periodic_schedule_rejected and test_do_dry_run_non_periodic_schedule_rejected tests covering @once, @continuous, None, and asset schedules.
  • Updated existing test_no_schedule_dag for new exception behavior.
  • Updated test fixtures in DAG response tests, DagCard UI tests, and airflow-ctl tests.

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

Generated-by: Claude Opus 4.6 following the guidelines


  • 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.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_backfillable to DAG-related API response models and OpenAPI specs (public + UI).
  • Validate backfills against dag.timetable.periodic (rejecting None, @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
FileDescription
uv.lockUpdates lockfile metadata/deps (includes OAuth/authlib-related changes).
airflow-ctl/src/airflowctl/api/datamodels/generated.pyAdds is_backfillable to generated CLI client DAG response models.
airflow-core/src/airflow/api_fastapi/core_api/datamodels/dags.pyIntroduces computed is_backfillable on DAGResponse (and inheritors).
airflow-core/src/airflow/models/backfill.pyRenames schedule exception + switches backfill validation to timetable.periodic.
airflow-core/src/airflow/api_fastapi/core_api/routes/public/backfills.pyUpdates route exception handling to the renamed exception.
airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yamlPublishes is_backfillable in public OpenAPI schema for DAG responses.
airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yamlPublishes is_backfillable in private UI OpenAPI schema for DAG responses.
airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.tsUpdates generated TS types to include is_backfillable.
airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.tsUpdates generated TS schemas to include is_backfillable as required/readOnly.
airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGModal.tsxDisables/gates Backfill option using dag.is_backfillable instead of hasSchedule.
airflow-core/src/airflow/ui/public/i18n/locales/en/components.jsonReplaces tooltip string with scheduleNotBackfillable message.
airflow-core/tests/unit/models/test_backfill.pyAdds coverage for rejecting non-periodic schedules in create/dry-run helpers.
airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_backfills.pyUpdates validation expectations for non-periodic schedules.
airflow-core/tests/unit/api_fastapi/core_api/datamodels/test_dags.pyAdds unit tests for DAGResponse.is_backfillable computation.
airflow-core/tests/unit/api_fastapi/core_api/datamodels/__init__.pyAdds package init for new datamodel tests directory.

Comment threadairflow-core/src/airflow/models/backfill.py
@Dev-iL
Dev-iLforce-pushed the 2604/invalid_schedule branch 7 times, most recently from b45539e to 33e3f8fCompareApril 4, 2026 15:31

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.owners is typed as list[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 scheduleNotBackfillable message in English, which is a localization regression compared to the removed translated tooltip. 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.

Comment threadairflow-core/src/airflow/cli/commands/dag_command.py Outdated
Comment threadairflow-core/src/airflow/models/backfill.py Outdated

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good overall. Just a few nits and we should be good to merge.

Comment threadairflow-core/src/airflow/cli/commands/dag_command.py Outdated
Comment threadairflow-core/src/airflow/ui/public/i18n/locales/ca/components.json Outdated
@Dev-iL
Dev-iLforce-pushed the 2604/invalid_schedule branch from d888c11 to 27b30a1CompareApril 14, 2026 03:52
@pierrejeambrunpierrejeambrun added this to the Airflow 3.3.0 milestone Apr 14, 2026
@pierrejeambrun
pierrejeambrun merged commit b3f9107 into apache:mainApr 14, 2026
141 checks passed
@Dev-iL
Dev-iL deleted the 2604/invalid_schedule branch April 14, 2026 14:45
Lee-W added a commit to astronomer/airflow that referenced this pull request Aug 3, 2026
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.
Lee-W added a commit to astronomer/airflow that referenced this pull request Aug 3, 2026
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.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:airflow-ctlarea:APIAirflow's REST/HTTP APIarea:translationsarea:UIRelated to UI/UX. For Frontend Developers.translation:default

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@Dev-iL@pierrejeambrun@eladkal
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Add is_backfillable property to DAG API responses - #64644

Merged
pierrejeambrun merged 1 commit into
apache:mainfrom
Dev-iL:2604/invalid_schedule
Apr 14, 2026
Merged

Add is_backfillable property to DAG API responses#64644
pierrejeambrun merged 1 commit into
apache:mainfrom
Dev-iL:2604/invalid_schedule

Conversation

@Dev-iL

@Dev-iLDev-iL commented Apr 2, 2026

Copy link
Copy Markdown
Collaborator

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_types to exclude BACKFILL_JOB had no upfront indication that backfilling is disabled.

Summary

  • Adds a timetable_periodic boolean column to DagModel via Alembic migration (following the timetable_partitioned pattern), set from dag.timetable.periodic during DAG sync.
  • Adds a computed is_backfillable field to DAG API responses that unifies both schedule compatibility (timetable_periodic) and run-type permissions (allowed_run_types) into a single source of truth.
  • Replaces the backend's string-based timetable_summary == "None" check with a proper timetable.periodic check in both _do_dry_run and _create_backfill, catching all non-periodic schedules (@once, @continuous, asset-triggered, partitioned asset) — not just unscheduled DAGs.
  • Adds allowed_run_types validation to _do_dry_run (previously only in _create_backfill), ensuring dry-run and create return consistent errors.
  • Renames DagNoScheduleException to DagNonPeriodicScheduleException to reflect the broader validation.
  • Updates the UI to use the new is_backfillable field instead of the hasSchedule heuristic, so the Backfill option is correctly disabled for all non-backfillable DAGs.
image

Changes

Migration:

  • Migration 0111 adds timetable_periodic Boolean column to the dag table (server_default="0", nullable=False).
  • dag_processing/collection.py sets dm.timetable_periodic = dag.timetable.periodic during DAG sync.

API / Models:

  • DagModel declares timetable_periodic: Mapped[bool].
  • DAGResponse.is_backfillable — computed field: True only when timetable_periodic is True AND BACKFILL_JOB is permitted by allowed_run_types.
  • backfill.py — both _create_backfill and _do_dry_run check dag.timetable.periodic and allowed_run_types.
  • Renamed DagNoScheduleException -> DagNonPeriodicScheduleException.
  • dag_command.pyis_backfillable computed from both periodic and allowed_run_types.

UI:

  • TriggerDAGModal.tsx uses is_backfillable to gate the Backfill radio option. hasSchedule is kept for TriggerDAGForm (controls data interval display — separate concern).
  • Updated i18n strings (renamed backfill.tooltip to backfill.scheduleNotBackfillable in all 21 locales).

Tests:

  • New TestIsBackfillable tests covering: non-periodic, periodic, allowed_run_types=None, backfill included/excluded, and the combined non-periodic+allowed case.
  • New test_create_backfill_non_periodic_schedule_rejected and test_do_dry_run_non_periodic_schedule_rejected tests covering @once, @continuous, None, and asset schedules.
  • Updated existing test_no_schedule_dag for new exception behavior.
  • Updated test fixtures in DAG response tests, DagCard UI tests, and airflow-ctl tests.

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

Generated-by: Claude Opus 4.6 following the guidelines


  • 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.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_backfillable to DAG-related API response models and OpenAPI specs (public + UI).
  • Validate backfills against dag.timetable.periodic (rejecting None, @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
FileDescription
uv.lockUpdates lockfile metadata/deps (includes OAuth/authlib-related changes).
airflow-ctl/src/airflowctl/api/datamodels/generated.pyAdds is_backfillable to generated CLI client DAG response models.
airflow-core/src/airflow/api_fastapi/core_api/datamodels/dags.pyIntroduces computed is_backfillable on DAGResponse (and inheritors).
airflow-core/src/airflow/models/backfill.pyRenames schedule exception + switches backfill validation to timetable.periodic.
airflow-core/src/airflow/api_fastapi/core_api/routes/public/backfills.pyUpdates route exception handling to the renamed exception.
airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yamlPublishes is_backfillable in public OpenAPI schema for DAG responses.
airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yamlPublishes is_backfillable in private UI OpenAPI schema for DAG responses.
airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.tsUpdates generated TS types to include is_backfillable.
airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.tsUpdates generated TS schemas to include is_backfillable as required/readOnly.
airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGModal.tsxDisables/gates Backfill option using dag.is_backfillable instead of hasSchedule.
airflow-core/src/airflow/ui/public/i18n/locales/en/components.jsonReplaces tooltip string with scheduleNotBackfillable message.
airflow-core/tests/unit/models/test_backfill.pyAdds coverage for rejecting non-periodic schedules in create/dry-run helpers.
airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_backfills.pyUpdates validation expectations for non-periodic schedules.
airflow-core/tests/unit/api_fastapi/core_api/datamodels/test_dags.pyAdds unit tests for DAGResponse.is_backfillable computation.
airflow-core/tests/unit/api_fastapi/core_api/datamodels/__init__.pyAdds package init for new datamodel tests directory.

Comment threadairflow-core/src/airflow/models/backfill.py
@Dev-iL
Dev-iLforce-pushed the 2604/invalid_schedule branch 7 times, most recently from b45539e to 33e3f8fCompareApril 4, 2026 15:31

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.owners is typed as list[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 scheduleNotBackfillable message in English, which is a localization regression compared to the removed translated tooltip. 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.

Comment threadairflow-core/src/airflow/cli/commands/dag_command.py Outdated
Comment threadairflow-core/src/airflow/models/backfill.py Outdated

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good overall. Just a few nits and we should be good to merge.

Comment threadairflow-core/src/airflow/cli/commands/dag_command.py Outdated
Comment threadairflow-core/src/airflow/ui/public/i18n/locales/ca/components.json Outdated
@Dev-iL
Dev-iLforce-pushed the 2604/invalid_schedule branch from d888c11 to 27b30a1CompareApril 14, 2026 03:52
@pierrejeambrunpierrejeambrun added this to the Airflow 3.3.0 milestone Apr 14, 2026
@pierrejeambrun
pierrejeambrun merged commit b3f9107 into apache:mainApr 14, 2026
141 checks passed
@Dev-iL
Dev-iL deleted the 2604/invalid_schedule branch April 14, 2026 14:45
Lee-W added a commit to astronomer/airflow that referenced this pull request Aug 3, 2026
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.
Lee-W added a commit to astronomer/airflow that referenced this pull request Aug 3, 2026
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.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:airflow-ctlarea:APIAirflow's REST/HTTP APIarea:translationsarea:UIRelated to UI/UX. For Frontend Developers.translation:default

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@Dev-iL@pierrejeambrun@eladkal
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add is_backfillable property to DAG API responses - #64644

Merged
pierrejeambrun merged 1 commit into
apache:mainfrom
Dev-iL:2604/invalid_schedule
Apr 14, 2026
Merged

Add is_backfillable property to DAG API responses#64644
pierrejeambrun merged 1 commit into
apache:mainfrom
Dev-iL:2604/invalid_schedule

Conversation

@Dev-iL

@Dev-iLDev-iL commented Apr 2, 2026

Copy link
Copy Markdown
Collaborator

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_types to exclude BACKFILL_JOB had no upfront indication that backfilling is disabled.

Summary

  • Adds a timetable_periodic boolean column to DagModel via Alembic migration (following the timetable_partitioned pattern), set from dag.timetable.periodic during DAG sync.
  • Adds a computed is_backfillable field to DAG API responses that unifies both schedule compatibility (timetable_periodic) and run-type permissions (allowed_run_types) into a single source of truth.
  • Replaces the backend's string-based timetable_summary == "None" check with a proper timetable.periodic check in both _do_dry_run and _create_backfill, catching all non-periodic schedules (@once, @continuous, asset-triggered, partitioned asset) — not just unscheduled DAGs.
  • Adds allowed_run_types validation to _do_dry_run (previously only in _create_backfill), ensuring dry-run and create return consistent errors.
  • Renames DagNoScheduleException to DagNonPeriodicScheduleException to reflect the broader validation.
  • Updates the UI to use the new is_backfillable field instead of the hasSchedule heuristic, so the Backfill option is correctly disabled for all non-backfillable DAGs.
image

Changes

Migration:

  • Migration 0111 adds timetable_periodic Boolean column to the dag table (server_default="0", nullable=False).
  • dag_processing/collection.py sets dm.timetable_periodic = dag.timetable.periodic during DAG sync.

API / Models:

  • DagModel declares timetable_periodic: Mapped[bool].
  • DAGResponse.is_backfillable — computed field: True only when timetable_periodic is True AND BACKFILL_JOB is permitted by allowed_run_types.
  • backfill.py — both _create_backfill and _do_dry_run check dag.timetable.periodic and allowed_run_types.
  • Renamed DagNoScheduleException -> DagNonPeriodicScheduleException.
  • dag_command.pyis_backfillable computed from both periodic and allowed_run_types.

UI:

  • TriggerDAGModal.tsx uses is_backfillable to gate the Backfill radio option. hasSchedule is kept for TriggerDAGForm (controls data interval display — separate concern).
  • Updated i18n strings (renamed backfill.tooltip to backfill.scheduleNotBackfillable in all 21 locales).

Tests:

  • New TestIsBackfillable tests covering: non-periodic, periodic, allowed_run_types=None, backfill included/excluded, and the combined non-periodic+allowed case.
  • New test_create_backfill_non_periodic_schedule_rejected and test_do_dry_run_non_periodic_schedule_rejected tests covering @once, @continuous, None, and asset schedules.
  • Updated existing test_no_schedule_dag for new exception behavior.
  • Updated test fixtures in DAG response tests, DagCard UI tests, and airflow-ctl tests.

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

Generated-by: Claude Opus 4.6 following the guidelines


  • 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.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_backfillable to DAG-related API response models and OpenAPI specs (public + UI).
  • Validate backfills against dag.timetable.periodic (rejecting None, @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
FileDescription
uv.lockUpdates lockfile metadata/deps (includes OAuth/authlib-related changes).
airflow-ctl/src/airflowctl/api/datamodels/generated.pyAdds is_backfillable to generated CLI client DAG response models.
airflow-core/src/airflow/api_fastapi/core_api/datamodels/dags.pyIntroduces computed is_backfillable on DAGResponse (and inheritors).
airflow-core/src/airflow/models/backfill.pyRenames schedule exception + switches backfill validation to timetable.periodic.
airflow-core/src/airflow/api_fastapi/core_api/routes/public/backfills.pyUpdates route exception handling to the renamed exception.
airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yamlPublishes is_backfillable in public OpenAPI schema for DAG responses.
airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yamlPublishes is_backfillable in private UI OpenAPI schema for DAG responses.
airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.tsUpdates generated TS types to include is_backfillable.
airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.tsUpdates generated TS schemas to include is_backfillable as required/readOnly.
airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGModal.tsxDisables/gates Backfill option using dag.is_backfillable instead of hasSchedule.
airflow-core/src/airflow/ui/public/i18n/locales/en/components.jsonReplaces tooltip string with scheduleNotBackfillable message.
airflow-core/tests/unit/models/test_backfill.pyAdds coverage for rejecting non-periodic schedules in create/dry-run helpers.
airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_backfills.pyUpdates validation expectations for non-periodic schedules.
airflow-core/tests/unit/api_fastapi/core_api/datamodels/test_dags.pyAdds unit tests for DAGResponse.is_backfillable computation.
airflow-core/tests/unit/api_fastapi/core_api/datamodels/__init__.pyAdds package init for new datamodel tests directory.

Comment threadairflow-core/src/airflow/models/backfill.py
@Dev-iL
Dev-iLforce-pushed the 2604/invalid_schedule branch 7 times, most recently from b45539e to 33e3f8fCompareApril 4, 2026 15:31

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.owners is typed as list[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 scheduleNotBackfillable message in English, which is a localization regression compared to the removed translated tooltip. 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.

Comment threadairflow-core/src/airflow/cli/commands/dag_command.py Outdated
Comment threadairflow-core/src/airflow/models/backfill.py Outdated

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good overall. Just a few nits and we should be good to merge.

Comment threadairflow-core/src/airflow/cli/commands/dag_command.py Outdated
Comment threadairflow-core/src/airflow/ui/public/i18n/locales/ca/components.json Outdated
@Dev-iL
Dev-iLforce-pushed the 2604/invalid_schedule branch from d888c11 to 27b30a1CompareApril 14, 2026 03:52
@pierrejeambrunpierrejeambrun added this to the Airflow 3.3.0 milestone Apr 14, 2026
@pierrejeambrun
pierrejeambrun merged commit b3f9107 into apache:mainApr 14, 2026
141 checks passed
@Dev-iL
Dev-iL deleted the 2604/invalid_schedule branch April 14, 2026 14:45
Lee-W added a commit to astronomer/airflow that referenced this pull request Aug 3, 2026
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.
Lee-W added a commit to astronomer/airflow that referenced this pull request Aug 3, 2026
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.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:airflow-ctlarea:APIAirflow's REST/HTTP APIarea:translationsarea:UIRelated to UI/UX. For Frontend Developers.translation:default

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@Dev-iL@pierrejeambrun@eladkal
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add is_backfillable property to DAG API responses - #64644

Merged
pierrejeambrun merged 1 commit into
apache:mainfrom
Dev-iL:2604/invalid_schedule
Apr 14, 2026
Merged

Add is_backfillable property to DAG API responses#64644
pierrejeambrun merged 1 commit into
apache:mainfrom
Dev-iL:2604/invalid_schedule

Conversation

@Dev-iL

@Dev-iLDev-iL commented Apr 2, 2026

Copy link
Copy Markdown
Collaborator

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_types to exclude BACKFILL_JOB had no upfront indication that backfilling is disabled.

Summary

  • Adds a timetable_periodic boolean column to DagModel via Alembic migration (following the timetable_partitioned pattern), set from dag.timetable.periodic during DAG sync.
  • Adds a computed is_backfillable field to DAG API responses that unifies both schedule compatibility (timetable_periodic) and run-type permissions (allowed_run_types) into a single source of truth.
  • Replaces the backend's string-based timetable_summary == "None" check with a proper timetable.periodic check in both _do_dry_run and _create_backfill, catching all non-periodic schedules (@once, @continuous, asset-triggered, partitioned asset) — not just unscheduled DAGs.
  • Adds allowed_run_types validation to _do_dry_run (previously only in _create_backfill), ensuring dry-run and create return consistent errors.
  • Renames DagNoScheduleException to DagNonPeriodicScheduleException to reflect the broader validation.
  • Updates the UI to use the new is_backfillable field instead of the hasSchedule heuristic, so the Backfill option is correctly disabled for all non-backfillable DAGs.
image

Changes

Migration:

  • Migration 0111 adds timetable_periodic Boolean column to the dag table (server_default="0", nullable=False).
  • dag_processing/collection.py sets dm.timetable_periodic = dag.timetable.periodic during DAG sync.

API / Models:

  • DagModel declares timetable_periodic: Mapped[bool].
  • DAGResponse.is_backfillable — computed field: True only when timetable_periodic is True AND BACKFILL_JOB is permitted by allowed_run_types.
  • backfill.py — both _create_backfill and _do_dry_run check dag.timetable.periodic and allowed_run_types.
  • Renamed DagNoScheduleException -> DagNonPeriodicScheduleException.
  • dag_command.pyis_backfillable computed from both periodic and allowed_run_types.

UI:

  • TriggerDAGModal.tsx uses is_backfillable to gate the Backfill radio option. hasSchedule is kept for TriggerDAGForm (controls data interval display — separate concern).
  • Updated i18n strings (renamed backfill.tooltip to backfill.scheduleNotBackfillable in all 21 locales).

Tests:

  • New TestIsBackfillable tests covering: non-periodic, periodic, allowed_run_types=None, backfill included/excluded, and the combined non-periodic+allowed case.
  • New test_create_backfill_non_periodic_schedule_rejected and test_do_dry_run_non_periodic_schedule_rejected tests covering @once, @continuous, None, and asset schedules.
  • Updated existing test_no_schedule_dag for new exception behavior.
  • Updated test fixtures in DAG response tests, DagCard UI tests, and airflow-ctl tests.

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

Generated-by: Claude Opus 4.6 following the guidelines


  • 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.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_backfillable to DAG-related API response models and OpenAPI specs (public + UI).
  • Validate backfills against dag.timetable.periodic (rejecting None, @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
FileDescription
uv.lockUpdates lockfile metadata/deps (includes OAuth/authlib-related changes).
airflow-ctl/src/airflowctl/api/datamodels/generated.pyAdds is_backfillable to generated CLI client DAG response models.
airflow-core/src/airflow/api_fastapi/core_api/datamodels/dags.pyIntroduces computed is_backfillable on DAGResponse (and inheritors).
airflow-core/src/airflow/models/backfill.pyRenames schedule exception + switches backfill validation to timetable.periodic.
airflow-core/src/airflow/api_fastapi/core_api/routes/public/backfills.pyUpdates route exception handling to the renamed exception.
airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yamlPublishes is_backfillable in public OpenAPI schema for DAG responses.
airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yamlPublishes is_backfillable in private UI OpenAPI schema for DAG responses.
airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.tsUpdates generated TS types to include is_backfillable.
airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.tsUpdates generated TS schemas to include is_backfillable as required/readOnly.
airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGModal.tsxDisables/gates Backfill option using dag.is_backfillable instead of hasSchedule.
airflow-core/src/airflow/ui/public/i18n/locales/en/components.jsonReplaces tooltip string with scheduleNotBackfillable message.
airflow-core/tests/unit/models/test_backfill.pyAdds coverage for rejecting non-periodic schedules in create/dry-run helpers.
airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_backfills.pyUpdates validation expectations for non-periodic schedules.
airflow-core/tests/unit/api_fastapi/core_api/datamodels/test_dags.pyAdds unit tests for DAGResponse.is_backfillable computation.
airflow-core/tests/unit/api_fastapi/core_api/datamodels/__init__.pyAdds package init for new datamodel tests directory.

Comment threadairflow-core/src/airflow/models/backfill.py
@Dev-iL
Dev-iLforce-pushed the 2604/invalid_schedule branch 7 times, most recently from b45539e to 33e3f8fCompareApril 4, 2026 15:31

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.owners is typed as list[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 scheduleNotBackfillable message in English, which is a localization regression compared to the removed translated tooltip. 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.

Comment threadairflow-core/src/airflow/cli/commands/dag_command.py Outdated
Comment threadairflow-core/src/airflow/models/backfill.py Outdated

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good overall. Just a few nits and we should be good to merge.

Comment threadairflow-core/src/airflow/cli/commands/dag_command.py Outdated
Comment threadairflow-core/src/airflow/ui/public/i18n/locales/ca/components.json Outdated
@Dev-iL
Dev-iLforce-pushed the 2604/invalid_schedule branch from d888c11 to 27b30a1CompareApril 14, 2026 03:52
@pierrejeambrunpierrejeambrun added this to the Airflow 3.3.0 milestone Apr 14, 2026
@pierrejeambrun
pierrejeambrun merged commit b3f9107 into apache:mainApr 14, 2026
141 checks passed
@Dev-iL
Dev-iL deleted the 2604/invalid_schedule branch April 14, 2026 14:45
Lee-W added a commit to astronomer/airflow that referenced this pull request Aug 3, 2026
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.
Lee-W added a commit to astronomer/airflow that referenced this pull request Aug 3, 2026
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.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:airflow-ctlarea:APIAirflow's REST/HTTP APIarea:translationsarea:UIRelated to UI/UX. For Frontend Developers.translation:default

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@Dev-iL@pierrejeambrun@eladkal
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Add is_backfillable property to DAG API responses - #64644

Merged
pierrejeambrun merged 1 commit into
apache:mainfrom
Dev-iL:2604/invalid_schedule
Apr 14, 2026
Merged

Add is_backfillable property to DAG API responses#64644
pierrejeambrun merged 1 commit into
apache:mainfrom
Dev-iL:2604/invalid_schedule

Conversation

@Dev-iL

@Dev-iLDev-iL commented Apr 2, 2026

Copy link
Copy Markdown
Collaborator

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_types to exclude BACKFILL_JOB had no upfront indication that backfilling is disabled.

Summary

  • Adds a timetable_periodic boolean column to DagModel via Alembic migration (following the timetable_partitioned pattern), set from dag.timetable.periodic during DAG sync.
  • Adds a computed is_backfillable field to DAG API responses that unifies both schedule compatibility (timetable_periodic) and run-type permissions (allowed_run_types) into a single source of truth.
  • Replaces the backend's string-based timetable_summary == "None" check with a proper timetable.periodic check in both _do_dry_run and _create_backfill, catching all non-periodic schedules (@once, @continuous, asset-triggered, partitioned asset) — not just unscheduled DAGs.
  • Adds allowed_run_types validation to _do_dry_run (previously only in _create_backfill), ensuring dry-run and create return consistent errors.
  • Renames DagNoScheduleException to DagNonPeriodicScheduleException to reflect the broader validation.
  • Updates the UI to use the new is_backfillable field instead of the hasSchedule heuristic, so the Backfill option is correctly disabled for all non-backfillable DAGs.
image

Changes

Migration:

  • Migration 0111 adds timetable_periodic Boolean column to the dag table (server_default="0", nullable=False).
  • dag_processing/collection.py sets dm.timetable_periodic = dag.timetable.periodic during DAG sync.

API / Models:

  • DagModel declares timetable_periodic: Mapped[bool].
  • DAGResponse.is_backfillable — computed field: True only when timetable_periodic is True AND BACKFILL_JOB is permitted by allowed_run_types.
  • backfill.py — both _create_backfill and _do_dry_run check dag.timetable.periodic and allowed_run_types.
  • Renamed DagNoScheduleException -> DagNonPeriodicScheduleException.
  • dag_command.pyis_backfillable computed from both periodic and allowed_run_types.

UI:

  • TriggerDAGModal.tsx uses is_backfillable to gate the Backfill radio option. hasSchedule is kept for TriggerDAGForm (controls data interval display — separate concern).
  • Updated i18n strings (renamed backfill.tooltip to backfill.scheduleNotBackfillable in all 21 locales).

Tests:

  • New TestIsBackfillable tests covering: non-periodic, periodic, allowed_run_types=None, backfill included/excluded, and the combined non-periodic+allowed case.
  • New test_create_backfill_non_periodic_schedule_rejected and test_do_dry_run_non_periodic_schedule_rejected tests covering @once, @continuous, None, and asset schedules.
  • Updated existing test_no_schedule_dag for new exception behavior.
  • Updated test fixtures in DAG response tests, DagCard UI tests, and airflow-ctl tests.

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

Generated-by: Claude Opus 4.6 following the guidelines


  • 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.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_backfillable to DAG-related API response models and OpenAPI specs (public + UI).
  • Validate backfills against dag.timetable.periodic (rejecting None, @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
FileDescription
uv.lockUpdates lockfile metadata/deps (includes OAuth/authlib-related changes).
airflow-ctl/src/airflowctl/api/datamodels/generated.pyAdds is_backfillable to generated CLI client DAG response models.
airflow-core/src/airflow/api_fastapi/core_api/datamodels/dags.pyIntroduces computed is_backfillable on DAGResponse (and inheritors).
airflow-core/src/airflow/models/backfill.pyRenames schedule exception + switches backfill validation to timetable.periodic.
airflow-core/src/airflow/api_fastapi/core_api/routes/public/backfills.pyUpdates route exception handling to the renamed exception.
airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yamlPublishes is_backfillable in public OpenAPI schema for DAG responses.
airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yamlPublishes is_backfillable in private UI OpenAPI schema for DAG responses.
airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.tsUpdates generated TS types to include is_backfillable.
airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.tsUpdates generated TS schemas to include is_backfillable as required/readOnly.
airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGModal.tsxDisables/gates Backfill option using dag.is_backfillable instead of hasSchedule.
airflow-core/src/airflow/ui/public/i18n/locales/en/components.jsonReplaces tooltip string with scheduleNotBackfillable message.
airflow-core/tests/unit/models/test_backfill.pyAdds coverage for rejecting non-periodic schedules in create/dry-run helpers.
airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_backfills.pyUpdates validation expectations for non-periodic schedules.
airflow-core/tests/unit/api_fastapi/core_api/datamodels/test_dags.pyAdds unit tests for DAGResponse.is_backfillable computation.
airflow-core/tests/unit/api_fastapi/core_api/datamodels/__init__.pyAdds package init for new datamodel tests directory.

Comment threadairflow-core/src/airflow/models/backfill.py
@Dev-iL
Dev-iLforce-pushed the 2604/invalid_schedule branch 7 times, most recently from b45539e to 33e3f8fCompareApril 4, 2026 15:31

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.owners is typed as list[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 scheduleNotBackfillable message in English, which is a localization regression compared to the removed translated tooltip. 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.

Comment threadairflow-core/src/airflow/cli/commands/dag_command.py Outdated
Comment threadairflow-core/src/airflow/models/backfill.py Outdated

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good overall. Just a few nits and we should be good to merge.

Comment threadairflow-core/src/airflow/cli/commands/dag_command.py Outdated
Comment threadairflow-core/src/airflow/ui/public/i18n/locales/ca/components.json Outdated
@Dev-iL
Dev-iLforce-pushed the 2604/invalid_schedule branch from d888c11 to 27b30a1CompareApril 14, 2026 03:52
@pierrejeambrunpierrejeambrun added this to the Airflow 3.3.0 milestone Apr 14, 2026
@pierrejeambrun
pierrejeambrun merged commit b3f9107 into apache:mainApr 14, 2026
141 checks passed
@Dev-iL
Dev-iL deleted the 2604/invalid_schedule branch April 14, 2026 14:45
Lee-W added a commit to astronomer/airflow that referenced this pull request Aug 3, 2026
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.
Lee-W added a commit to astronomer/airflow that referenced this pull request Aug 3, 2026
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.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:airflow-ctlarea:APIAirflow's REST/HTTP APIarea:translationsarea:UIRelated to UI/UX. For Frontend Developers.translation:default

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@Dev-iL@pierrejeambrun@eladkal
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add is_backfillable property to DAG API responses - #64644

Merged
pierrejeambrun merged 1 commit into
apache:mainfrom
Dev-iL:2604/invalid_schedule
Apr 14, 2026
Merged

Add is_backfillable property to DAG API responses#64644
pierrejeambrun merged 1 commit into
apache:mainfrom
Dev-iL:2604/invalid_schedule

Conversation

@Dev-iL

@Dev-iLDev-iL commented Apr 2, 2026

Copy link
Copy Markdown
Collaborator

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_types to exclude BACKFILL_JOB had no upfront indication that backfilling is disabled.

Summary

  • Adds a timetable_periodic boolean column to DagModel via Alembic migration (following the timetable_partitioned pattern), set from dag.timetable.periodic during DAG sync.
  • Adds a computed is_backfillable field to DAG API responses that unifies both schedule compatibility (timetable_periodic) and run-type permissions (allowed_run_types) into a single source of truth.
  • Replaces the backend's string-based timetable_summary == "None" check with a proper timetable.periodic check in both _do_dry_run and _create_backfill, catching all non-periodic schedules (@once, @continuous, asset-triggered, partitioned asset) — not just unscheduled DAGs.
  • Adds allowed_run_types validation to _do_dry_run (previously only in _create_backfill), ensuring dry-run and create return consistent errors.
  • Renames DagNoScheduleException to DagNonPeriodicScheduleException to reflect the broader validation.
  • Updates the UI to use the new is_backfillable field instead of the hasSchedule heuristic, so the Backfill option is correctly disabled for all non-backfillable DAGs.
image

Changes

Migration:

  • Migration 0111 adds timetable_periodic Boolean column to the dag table (server_default="0", nullable=False).
  • dag_processing/collection.py sets dm.timetable_periodic = dag.timetable.periodic during DAG sync.

API / Models:

  • DagModel declares timetable_periodic: Mapped[bool].
  • DAGResponse.is_backfillable — computed field: True only when timetable_periodic is True AND BACKFILL_JOB is permitted by allowed_run_types.
  • backfill.py — both _create_backfill and _do_dry_run check dag.timetable.periodic and allowed_run_types.
  • Renamed DagNoScheduleException -> DagNonPeriodicScheduleException.
  • dag_command.pyis_backfillable computed from both periodic and allowed_run_types.

UI:

  • TriggerDAGModal.tsx uses is_backfillable to gate the Backfill radio option. hasSchedule is kept for TriggerDAGForm (controls data interval display — separate concern).
  • Updated i18n strings (renamed backfill.tooltip to backfill.scheduleNotBackfillable in all 21 locales).

Tests:

  • New TestIsBackfillable tests covering: non-periodic, periodic, allowed_run_types=None, backfill included/excluded, and the combined non-periodic+allowed case.
  • New test_create_backfill_non_periodic_schedule_rejected and test_do_dry_run_non_periodic_schedule_rejected tests covering @once, @continuous, None, and asset schedules.
  • Updated existing test_no_schedule_dag for new exception behavior.
  • Updated test fixtures in DAG response tests, DagCard UI tests, and airflow-ctl tests.

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

Generated-by: Claude Opus 4.6 following the guidelines


  • 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.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_backfillable to DAG-related API response models and OpenAPI specs (public + UI).
  • Validate backfills against dag.timetable.periodic (rejecting None, @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
FileDescription
uv.lockUpdates lockfile metadata/deps (includes OAuth/authlib-related changes).
airflow-ctl/src/airflowctl/api/datamodels/generated.pyAdds is_backfillable to generated CLI client DAG response models.
airflow-core/src/airflow/api_fastapi/core_api/datamodels/dags.pyIntroduces computed is_backfillable on DAGResponse (and inheritors).
airflow-core/src/airflow/models/backfill.pyRenames schedule exception + switches backfill validation to timetable.periodic.
airflow-core/src/airflow/api_fastapi/core_api/routes/public/backfills.pyUpdates route exception handling to the renamed exception.
airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yamlPublishes is_backfillable in public OpenAPI schema for DAG responses.
airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yamlPublishes is_backfillable in private UI OpenAPI schema for DAG responses.
airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.tsUpdates generated TS types to include is_backfillable.
airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.tsUpdates generated TS schemas to include is_backfillable as required/readOnly.
airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGModal.tsxDisables/gates Backfill option using dag.is_backfillable instead of hasSchedule.
airflow-core/src/airflow/ui/public/i18n/locales/en/components.jsonReplaces tooltip string with scheduleNotBackfillable message.
airflow-core/tests/unit/models/test_backfill.pyAdds coverage for rejecting non-periodic schedules in create/dry-run helpers.
airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_backfills.pyUpdates validation expectations for non-periodic schedules.
airflow-core/tests/unit/api_fastapi/core_api/datamodels/test_dags.pyAdds unit tests for DAGResponse.is_backfillable computation.
airflow-core/tests/unit/api_fastapi/core_api/datamodels/__init__.pyAdds package init for new datamodel tests directory.

Comment threadairflow-core/src/airflow/models/backfill.py
@Dev-iL
Dev-iLforce-pushed the 2604/invalid_schedule branch 7 times, most recently from b45539e to 33e3f8fCompareApril 4, 2026 15:31

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.owners is typed as list[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 scheduleNotBackfillable message in English, which is a localization regression compared to the removed translated tooltip. 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.

Comment threadairflow-core/src/airflow/cli/commands/dag_command.py Outdated
Comment threadairflow-core/src/airflow/models/backfill.py Outdated

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good overall. Just a few nits and we should be good to merge.

Comment threadairflow-core/src/airflow/cli/commands/dag_command.py Outdated
Comment threadairflow-core/src/airflow/ui/public/i18n/locales/ca/components.json Outdated
@Dev-iL
Dev-iLforce-pushed the 2604/invalid_schedule branch from d888c11 to 27b30a1CompareApril 14, 2026 03:52
@pierrejeambrunpierrejeambrun added this to the Airflow 3.3.0 milestone Apr 14, 2026
@pierrejeambrun
pierrejeambrun merged commit b3f9107 into apache:mainApr 14, 2026
141 checks passed
@Dev-iL
Dev-iL deleted the 2604/invalid_schedule branch April 14, 2026 14:45
Lee-W added a commit to astronomer/airflow that referenced this pull request Aug 3, 2026
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.
Lee-W added a commit to astronomer/airflow that referenced this pull request Aug 3, 2026
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.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:airflow-ctlarea:APIAirflow's REST/HTTP APIarea:translationsarea:UIRelated to UI/UX. For Frontend Developers.translation:default

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@Dev-iL@pierrejeambrun@eladkal
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add is_backfillable property to DAG API responses - #64644

Merged
pierrejeambrun merged 1 commit into
apache:mainfrom
Dev-iL:2604/invalid_schedule
Apr 14, 2026
Merged

Add is_backfillable property to DAG API responses#64644
pierrejeambrun merged 1 commit into
apache:mainfrom
Dev-iL:2604/invalid_schedule

Conversation

@Dev-iL

@Dev-iLDev-iL commented Apr 2, 2026

Copy link
Copy Markdown
Collaborator

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_types to exclude BACKFILL_JOB had no upfront indication that backfilling is disabled.

Summary

  • Adds a timetable_periodic boolean column to DagModel via Alembic migration (following the timetable_partitioned pattern), set from dag.timetable.periodic during DAG sync.
  • Adds a computed is_backfillable field to DAG API responses that unifies both schedule compatibility (timetable_periodic) and run-type permissions (allowed_run_types) into a single source of truth.
  • Replaces the backend's string-based timetable_summary == "None" check with a proper timetable.periodic check in both _do_dry_run and _create_backfill, catching all non-periodic schedules (@once, @continuous, asset-triggered, partitioned asset) — not just unscheduled DAGs.
  • Adds allowed_run_types validation to _do_dry_run (previously only in _create_backfill), ensuring dry-run and create return consistent errors.
  • Renames DagNoScheduleException to DagNonPeriodicScheduleException to reflect the broader validation.
  • Updates the UI to use the new is_backfillable field instead of the hasSchedule heuristic, so the Backfill option is correctly disabled for all non-backfillable DAGs.
image

Changes

Migration:

  • Migration 0111 adds timetable_periodic Boolean column to the dag table (server_default="0", nullable=False).
  • dag_processing/collection.py sets dm.timetable_periodic = dag.timetable.periodic during DAG sync.

API / Models:

  • DagModel declares timetable_periodic: Mapped[bool].
  • DAGResponse.is_backfillable — computed field: True only when timetable_periodic is True AND BACKFILL_JOB is permitted by allowed_run_types.
  • backfill.py — both _create_backfill and _do_dry_run check dag.timetable.periodic and allowed_run_types.
  • Renamed DagNoScheduleException -> DagNonPeriodicScheduleException.
  • dag_command.pyis_backfillable computed from both periodic and allowed_run_types.

UI:

  • TriggerDAGModal.tsx uses is_backfillable to gate the Backfill radio option. hasSchedule is kept for TriggerDAGForm (controls data interval display — separate concern).
  • Updated i18n strings (renamed backfill.tooltip to backfill.scheduleNotBackfillable in all 21 locales).

Tests:

  • New TestIsBackfillable tests covering: non-periodic, periodic, allowed_run_types=None, backfill included/excluded, and the combined non-periodic+allowed case.
  • New test_create_backfill_non_periodic_schedule_rejected and test_do_dry_run_non_periodic_schedule_rejected tests covering @once, @continuous, None, and asset schedules.
  • Updated existing test_no_schedule_dag for new exception behavior.
  • Updated test fixtures in DAG response tests, DagCard UI tests, and airflow-ctl tests.

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

Generated-by: Claude Opus 4.6 following the guidelines


  • 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.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_backfillable to DAG-related API response models and OpenAPI specs (public + UI).
  • Validate backfills against dag.timetable.periodic (rejecting None, @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
FileDescription
uv.lockUpdates lockfile metadata/deps (includes OAuth/authlib-related changes).
airflow-ctl/src/airflowctl/api/datamodels/generated.pyAdds is_backfillable to generated CLI client DAG response models.
airflow-core/src/airflow/api_fastapi/core_api/datamodels/dags.pyIntroduces computed is_backfillable on DAGResponse (and inheritors).
airflow-core/src/airflow/models/backfill.pyRenames schedule exception + switches backfill validation to timetable.periodic.
airflow-core/src/airflow/api_fastapi/core_api/routes/public/backfills.pyUpdates route exception handling to the renamed exception.
airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yamlPublishes is_backfillable in public OpenAPI schema for DAG responses.
airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yamlPublishes is_backfillable in private UI OpenAPI schema for DAG responses.
airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.tsUpdates generated TS types to include is_backfillable.
airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.tsUpdates generated TS schemas to include is_backfillable as required/readOnly.
airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGModal.tsxDisables/gates Backfill option using dag.is_backfillable instead of hasSchedule.
airflow-core/src/airflow/ui/public/i18n/locales/en/components.jsonReplaces tooltip string with scheduleNotBackfillable message.
airflow-core/tests/unit/models/test_backfill.pyAdds coverage for rejecting non-periodic schedules in create/dry-run helpers.
airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_backfills.pyUpdates validation expectations for non-periodic schedules.
airflow-core/tests/unit/api_fastapi/core_api/datamodels/test_dags.pyAdds unit tests for DAGResponse.is_backfillable computation.
airflow-core/tests/unit/api_fastapi/core_api/datamodels/__init__.pyAdds package init for new datamodel tests directory.

Comment threadairflow-core/src/airflow/models/backfill.py
@Dev-iL
Dev-iLforce-pushed the 2604/invalid_schedule branch 7 times, most recently from b45539e to 33e3f8fCompareApril 4, 2026 15:31

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.owners is typed as list[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 scheduleNotBackfillable message in English, which is a localization regression compared to the removed translated tooltip. 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.

Comment threadairflow-core/src/airflow/cli/commands/dag_command.py Outdated
Comment threadairflow-core/src/airflow/models/backfill.py Outdated

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good overall. Just a few nits and we should be good to merge.

Comment threadairflow-core/src/airflow/cli/commands/dag_command.py Outdated
Comment threadairflow-core/src/airflow/ui/public/i18n/locales/ca/components.json Outdated
@Dev-iL
Dev-iLforce-pushed the 2604/invalid_schedule branch from d888c11 to 27b30a1CompareApril 14, 2026 03:52
@pierrejeambrunpierrejeambrun added this to the Airflow 3.3.0 milestone Apr 14, 2026
@pierrejeambrun
pierrejeambrun merged commit b3f9107 into apache:mainApr 14, 2026
141 checks passed
@Dev-iL
Dev-iL deleted the 2604/invalid_schedule branch April 14, 2026 14:45
Lee-W added a commit to astronomer/airflow that referenced this pull request Aug 3, 2026
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.
Lee-W added a commit to astronomer/airflow that referenced this pull request Aug 3, 2026
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.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:airflow-ctlarea:APIAirflow's REST/HTTP APIarea:translationsarea:UIRelated to UI/UX. For Frontend Developers.translation:default

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@Dev-iL@pierrejeambrun@eladkal
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Add is_backfillable property to DAG API responses - #64644

Merged
pierrejeambrun merged 1 commit into
apache:mainfrom
Dev-iL:2604/invalid_schedule
Apr 14, 2026
Merged

Add is_backfillable property to DAG API responses#64644
pierrejeambrun merged 1 commit into
apache:mainfrom
Dev-iL:2604/invalid_schedule

Conversation

@Dev-iL

@Dev-iLDev-iL commented Apr 2, 2026

Copy link
Copy Markdown
Collaborator

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_types to exclude BACKFILL_JOB had no upfront indication that backfilling is disabled.

Summary

  • Adds a timetable_periodic boolean column to DagModel via Alembic migration (following the timetable_partitioned pattern), set from dag.timetable.periodic during DAG sync.
  • Adds a computed is_backfillable field to DAG API responses that unifies both schedule compatibility (timetable_periodic) and run-type permissions (allowed_run_types) into a single source of truth.
  • Replaces the backend's string-based timetable_summary == "None" check with a proper timetable.periodic check in both _do_dry_run and _create_backfill, catching all non-periodic schedules (@once, @continuous, asset-triggered, partitioned asset) — not just unscheduled DAGs.
  • Adds allowed_run_types validation to _do_dry_run (previously only in _create_backfill), ensuring dry-run and create return consistent errors.
  • Renames DagNoScheduleException to DagNonPeriodicScheduleException to reflect the broader validation.
  • Updates the UI to use the new is_backfillable field instead of the hasSchedule heuristic, so the Backfill option is correctly disabled for all non-backfillable DAGs.
image

Changes

Migration:

  • Migration 0111 adds timetable_periodic Boolean column to the dag table (server_default="0", nullable=False).
  • dag_processing/collection.py sets dm.timetable_periodic = dag.timetable.periodic during DAG sync.

API / Models:

  • DagModel declares timetable_periodic: Mapped[bool].
  • DAGResponse.is_backfillable — computed field: True only when timetable_periodic is True AND BACKFILL_JOB is permitted by allowed_run_types.
  • backfill.py — both _create_backfill and _do_dry_run check dag.timetable.periodic and allowed_run_types.
  • Renamed DagNoScheduleException -> DagNonPeriodicScheduleException.
  • dag_command.pyis_backfillable computed from both periodic and allowed_run_types.

UI:

  • TriggerDAGModal.tsx uses is_backfillable to gate the Backfill radio option. hasSchedule is kept for TriggerDAGForm (controls data interval display — separate concern).
  • Updated i18n strings (renamed backfill.tooltip to backfill.scheduleNotBackfillable in all 21 locales).

Tests:

  • New TestIsBackfillable tests covering: non-periodic, periodic, allowed_run_types=None, backfill included/excluded, and the combined non-periodic+allowed case.
  • New test_create_backfill_non_periodic_schedule_rejected and test_do_dry_run_non_periodic_schedule_rejected tests covering @once, @continuous, None, and asset schedules.
  • Updated existing test_no_schedule_dag for new exception behavior.
  • Updated test fixtures in DAG response tests, DagCard UI tests, and airflow-ctl tests.

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

Generated-by: Claude Opus 4.6 following the guidelines


  • 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.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_backfillable to DAG-related API response models and OpenAPI specs (public + UI).
  • Validate backfills against dag.timetable.periodic (rejecting None, @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
FileDescription
uv.lockUpdates lockfile metadata/deps (includes OAuth/authlib-related changes).
airflow-ctl/src/airflowctl/api/datamodels/generated.pyAdds is_backfillable to generated CLI client DAG response models.
airflow-core/src/airflow/api_fastapi/core_api/datamodels/dags.pyIntroduces computed is_backfillable on DAGResponse (and inheritors).
airflow-core/src/airflow/models/backfill.pyRenames schedule exception + switches backfill validation to timetable.periodic.
airflow-core/src/airflow/api_fastapi/core_api/routes/public/backfills.pyUpdates route exception handling to the renamed exception.
airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yamlPublishes is_backfillable in public OpenAPI schema for DAG responses.
airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yamlPublishes is_backfillable in private UI OpenAPI schema for DAG responses.
airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.tsUpdates generated TS types to include is_backfillable.
airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.tsUpdates generated TS schemas to include is_backfillable as required/readOnly.
airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGModal.tsxDisables/gates Backfill option using dag.is_backfillable instead of hasSchedule.
airflow-core/src/airflow/ui/public/i18n/locales/en/components.jsonReplaces tooltip string with scheduleNotBackfillable message.
airflow-core/tests/unit/models/test_backfill.pyAdds coverage for rejecting non-periodic schedules in create/dry-run helpers.
airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_backfills.pyUpdates validation expectations for non-periodic schedules.
airflow-core/tests/unit/api_fastapi/core_api/datamodels/test_dags.pyAdds unit tests for DAGResponse.is_backfillable computation.
airflow-core/tests/unit/api_fastapi/core_api/datamodels/__init__.pyAdds package init for new datamodel tests directory.

Comment threadairflow-core/src/airflow/models/backfill.py
@Dev-iL
Dev-iLforce-pushed the 2604/invalid_schedule branch 7 times, most recently from b45539e to 33e3f8fCompareApril 4, 2026 15:31

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.owners is typed as list[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 scheduleNotBackfillable message in English, which is a localization regression compared to the removed translated tooltip. 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.

Comment threadairflow-core/src/airflow/cli/commands/dag_command.py Outdated
Comment threadairflow-core/src/airflow/models/backfill.py Outdated

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good overall. Just a few nits and we should be good to merge.

Comment threadairflow-core/src/airflow/cli/commands/dag_command.py Outdated
Comment threadairflow-core/src/airflow/ui/public/i18n/locales/ca/components.json Outdated
@Dev-iL
Dev-iLforce-pushed the 2604/invalid_schedule branch from d888c11 to 27b30a1CompareApril 14, 2026 03:52
@pierrejeambrunpierrejeambrun added this to the Airflow 3.3.0 milestone Apr 14, 2026
@pierrejeambrun
pierrejeambrun merged commit b3f9107 into apache:mainApr 14, 2026
141 checks passed
@Dev-iL
Dev-iL deleted the 2604/invalid_schedule branch April 14, 2026 14:45
Lee-W added a commit to astronomer/airflow that referenced this pull request Aug 3, 2026
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.
Lee-W added a commit to astronomer/airflow that referenced this pull request Aug 3, 2026
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.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:airflow-ctlarea:APIAirflow's REST/HTTP APIarea:translationsarea:UIRelated to UI/UX. For Frontend Developers.translation:default

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@Dev-iL@pierrejeambrun@eladkal