Skip to content

Fail queued DagRuns whose pinned dag version can no longer be resolved#70113

Open
kjh0623 wants to merge 1 commit into
apache:mainfrom
kjh0623:fix/scheduler-fail-queued-dagrun-unresolvable-version
Open

Fail queued DagRuns whose pinned dag version can no longer be resolved#70113
kjh0623 wants to merge 1 commit into
apache:mainfrom
kjh0623:fix/scheduler-fail-queued-dagrun-unresolvable-version

Conversation

@kjh0623

@kjh0623 kjh0623 commented Jul 20, 2026

Copy link
Copy Markdown

closes: #70056

Problem

A DagRun created pinned to a dag version (bundle_version set, created_dag_version_id populated) becomes unresolvable if that dag_version row is later deleted. The FK's ondelete="set null" clears created_dag_version_id while bundle_version stays set, so the pinned resolver in DBDagBag._version_from_dag_run returns None — it only falls back to the latest version for unpinned runs.

_start_queued_dagruns then can't resolve the serialized DAG and hits if not dag: log.error(...); continue, so the run is neither started nor failed. It is re-selected and skipped on every scheduler loop forever, with no failure signal, no metric, and a misleading log (DAG '...' not found in serialized_dag table — the DAG is in serialized_dag; only the pinned version is gone). No timeout applies to a QUEUED run in this state; in production a run sat QUEUED for 8+ hours until manually cleared.

Fix

Fail the run explicitly when its pinned version can't be resolved, mirroring how the same function already handles a SCHEDULED task instance whose serialized DAG can't be found (that path sets the TI to FAILED and moves on). The error message now names the unresolved created_dag_version_id / bundle_version.

This is option 1 from the issue. It doesn't change resolution for healthy or unpinned runs — only runs that are already unstartable get an explicit terminal state instead of being skipped indefinitely.

Tests

  • test_queued_dagrun_with_unresolvable_pinned_version_is_failed — reproduces the pinned+NULL state and asserts the run reaches FAILED across repeated loops instead of staying QUEUED.
  • test_queued_dagrun_without_bundle_version_falls_back_to_latest — contrast: same NULL created_dag_version_id but unpinned still falls back to the latest serialized version and starts (RUNNING), so the fix doesn't touch that path.

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

Generated-by: Claude Code following the guidelines

A DagRun created pinned to a dag version (bundle_version set,
created_dag_version_id populated) becomes unresolvable if that dag_version row
is later deleted: the FK's ondelete="set null" clears created_dag_version_id
while bundle_version stays set, so the pinned resolver returns None (it only
falls back to the latest version for unpinned runs). _start_queued_dagruns then
could not resolve the serialized DAG and skipped the run with
"DAG '...' not found in serialized_dag table" on every loop - the run was
neither started nor failed and stayed QUEUED indefinitely, with no failure
signal and a misleading log (the DAG is in serialized_dag; the pinned version
is not).

Fail such a run explicitly, mirroring how a SCHEDULED task instance whose
serialized DAG cannot be found is already failed in the same loop. Add a
regression test that the pinned-unresolvable run reaches FAILED instead of
being skipped forever, plus a contrast test that an unpinned run with the same
NULL created_dag_version_id still falls back to the latest version and starts.

Signed-off-by: kjh0623 <8412070+kjh0623@users.noreply.github.com>
@kjh0623

kjh0623 commented Jul 20, 2026

Copy link
Copy Markdown
Author

The failing "Tests (AMD)" job is not related to this change — it's a CI/MySQL DB-init issue, not a real test failure.

All 12 failures are ERROR at setup, i.e. the test DB never initialized. Root cause:

(1419, 'You do not have the SUPER privilege and binary logging is enabled
        (you might want to use the less safe log_bin_trust_function_creators variable)')

Migration 0042_..._add_uuid_primary_key_to_task_instance fails to CREATE FUNCTION uuid_generate_v7 because the MySQL user lacks SUPER and log_bin_trust_function_creators isn't enabled. Every subsequent UPDATE task_instance SET id = uuid_generate_v7(...) then fails with (1305) FUNCTION airflow.uuid_generate_v7 does not exist, cascading into all 12 setup errors. None of the failing tests touch the scheduler code in this PR.

Could a committer please re-run the failed jobs? 🙏

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

Labels

area:Scheduler including HA (high availability) scheduler

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Scheduler silently skips queued DagRuns forever when their pinned dag version can no longer be resolved

1 participant