Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions airflow-core/src/airflow/dag_processing/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -430,9 +430,10 @@ def deactivate_stale_dags(
for dag in dags_parsed:
# Dags whose bundle has been removed from config (bundle no longer active) are stale —
# the processor has stopped parsing their files, so the time-based check below would never fire.
if dag.bundle_name in inactive_bundles:
# Legacy DAGs with a NULL bundle_name (e.g. from Airflow 2.x) are also stale, as they will never be parsed.
if dag.bundle_name is None or dag.bundle_name in inactive_bundles:

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.

Won't the bundle name be fixed for null bundle_name after some times? Can you verify it

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The bundle_name is updated during parsing when the DAG processor reads the DAG files for a bundle (setting it to the name of the bundle, e.g., 'dags-folder').

However, in the upgrade scenario described in #60763, legacy DAGs are removed/deleted at the same time as the upgrade. Because their source files are gone, the DAG processor will never parse them again, and they will never have their bundle_name updated—it will remain None/NULL in the database forever.

Since their bundle_name remains None, they are never identified as stale under active bundles and thus are never deactivated, causing them to persist in the UI indefinitely. The query change ensures these legacy, deleted DAGs are caught and deactivated.

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.

Can you expand the in-code comment a bit? The context you provided is critical to understand why the check is needed, but the current wording fails to capture it.

self.log.info(
"Deactivating Dag %s. Its bundle %s is no longer active.",
"Deactivating Dag %s. Its bundle %s is no longer active or is NULL.",
dag.dag_id,
dag.bundle_name,
)
Expand Down
Loading