Fix deactivation of stale zip-packaged DAGs - #70586
Open
SamWheating wants to merge 1 commit into
Open
Conversation
SamWheating
force-pushed
the
sw-fix-stale-dag-detection-zip-packaged-dag-factory
branch
from
July 28, 2026 10:42
d66545a to
90e198c
Compare
SamWheating
marked this pull request as ready for review
July 28, 2026 10:44
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The Issue:
When deactivating DAGs, airflow compares the
DagFileStatgenerated by the manager to a DAG's fileloc in order to identify DAGs which were not seen on the most recent file parse.However, when processing zip-packaged DAGs, the DAG's relative_fileloc will be the value of
__file__reported by zipfile, which includes the inner path within the zip archive (ex:path/to/some/dag_package.zip/my_dag.py).Meanwhile the parsing stats used to index the
last_parseddictionary use the path of the archive file itself (ex:path/to/some/dag_package.zip) since there is a single entry per file-parsed.As a result, when looking at zip-packaged DAGs the
last_parsed.get()lookup here will never return a value:airflow/airflow-core/src/airflow/dag_processing/manager.py
Lines 481 to 489 in 1438ea3
And thus zip-packaged DAGs are never properly deactivated.
This issue doesn't surface too often, since most DAGs will also be caught by the
deactivate_deleted_dagsfunction which properly evaluates them based on inner paths. However for files which produce multiple DAGs ("dag factories") or DAGs which are renamed within a file, this second mechanism won't work either, since DAGs can be removed without the source file being removed.As a result, certain DAGs within a zip file will never be removed and airflow will continue to attempt to schedule and run them. I have reproduced this issue in breeze on the latest version of
main.The Fix:
Within the
deactivate_stale_dagsfunction, we can just remove the inner part of the fileloc for zip-packaged DAGs to obtain the actual filepath of the archive itself. I've added this as a private method on the class, but it could also be added as a property on theDAGmodel itself.Was generative AI tooling used to co-author this PR?
No