Repository navigation
Fix template file lookup for Dags packaged in zip files - #74542
Open
sjyangkevin wants to merge 1 commit into
Open
sjyangkevin wants to merge 1 commit into
sjyangkevin wants to merge 1 commit into
Conversation
A Dag imported from a zip archive has its folder inside the archive, which Jinja's FileSystemLoader cannot read. Template files shipped next to the Dag in the archive were therefore never found: parse-time resolution silently kept the raw file path, and every task run failed with TemplateNotFound before execute(). Pointing template_searchpath into the archive failed the same way, leaving Dag authors with only a workaround outside the public Task SDK interface.
sjyangkevin
force-pushed
the
fix-zipped-dag-template-files
branch
from
October 10, 2026 21:04
594297a to
849ba15
Compare
sjyangkevin
marked this pull request as ready for review
October 10, 2026 21:54
This branch has not been deployed
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.
Why
Dags packaged as zip archives could not use template files shipped inside the archive. For a zipped Dag,
dag.folderpoints into the archive (for example.../dags.zip), and Jinja'sFileSystemLoaderonly reads real directories. A templated field such as"query": "test_sql/test.sql"therefore failed every run with:At parse time the same lookup failed silently (only logged), and pointing
template_searchpathinto the archive failed the same way.create_template_env()now reads search-path entries that are, or point inside, a zip archive directly from the archive. Normal directories keep exactly the sameFileSystemLoaderas before. Both template environment builders (DAG.get_template_env()and the operator-levelrender_template_as_native_objoverride) go through this function.closes: #59310
related: #60999
How zip entries are handled
zipfile.is_zipfile(), so detection does not depend on the.zipextension or its case.split_template_path, as inFileSystemLoader, so they cannot leave the search root. Search-path prefixes containing..are not treated as archive paths.TemplateNotFoundwith thenot found in search path(s): ...message.Testing
DAGS.ZIP), zip-first ordering, both template environment builders with a.sqlpath nested in a dict, and parse-timeresolve_template_files()on a Dag imported by the zip importer. The other 9 pass onmainby design: they pin unchanged behaviour for non-zip search paths, the not-found message, and containment of template names. Each was checked to fail when the corresponding check in the new loader is removed.airflow dags testand the UI frombreeze start-airflow, with zipped Dags using a top-level template file, a.sqlpath nested in a dict,template_searchpathinside the archive, and{% include %}. All failed withTemplateNotFoundbefore this change and succeed after it. Unzipped copies of the same Dags succeed both before and after.BigQueryInsertJobOperator.execute(). The BigQuery call itself was not run (no GCP credentials), and this change does not touch it.mypy-task-sdk. Frombreeze verify:task-sdk-tests(3656 passed), core non-DB tests and core DB tests pass.Before/after reproduction in Breeze (
airflow dags test)repro.zipcontainsrepro_dags.py,scripts/hello.shandsql/query.sql. The same files unzipped provide thedir_*control Dags.reporter.zipis thetest.zipattached to the issue, unchanged.zip_top_levelbash_command="scripts/hello.sh"zip_nested_dict.sqlpath nested in a dict field, likeBigQueryInsertJobOperatorzip_searchpathtemplate_searchpathpointing to a folder inside the archivezip_include{% include 'scripts/hello.sh' %}test_import_path_dagdir_top_levelBefore (
main), trimmed to each Dag's result and its own task error:After (this PR):
test_import_path_dagnow gets through template rendering and fails inBigQueryInsertJobOperator.execute()withAirflowNotFoundException: The conn_id `google_cloud_default` isn't defined, since no GCP connection.repro_dags.pyscripts/hello.shisecho "hello from {{ dag.dag_id }} / {{ ti.task_id }}"andsql/query.sqlisSELECT column_a FROM test -- {{ dag.dag_id }}.Was generative AI tooling used to co-author this PR?
Generated-by: Claude Code (Opus 5.5) following the guidelines