Skip to content

Fix dag.test() failing for task ids with non-ASCII characters - #74472

Open
per-andersen wants to merge 1 commit into
apache:mainfrom
per-andersen:dagtest-fails-for-tasks-whose-task_id-contains-non-ascii-characters
Open

per-andersen wants to merge 1 commit into
apache:mainfrom
per-andersen:dagtest-fails-for-tasks-whose-task_id-contains-non-ascii-characters

Conversation

@per-andersen

@per-andersen per-andersen commented Oct 8, 2026 •

Copy link
Copy Markdown

dag.test() fails for any task whose task_id contains a non-ASCII character (for example Købsmoms) as soon as the task pushes an XCom, even though validate_key accepts these ids.

dag.test() serves the Execution API in-process: the Task SDK client talks to a2wsgi's ASGIMiddleware through httpx.WSGITransport. httpx puts the percent-decoded path into PATH_INFO as a plain str, while a2wsgi follows PEP 3333 and decodes PATH_INFO as UTF-8 bytes carried in a latin-1 string. A non-ASCII path segment therefore fails in a2wsgi.asgi.build_scope, with UnicodeDecodeError for characters such as ø and UnicodeEncodeError for characters outside Latin-1 such as タ.

This PR subclasses a2wsgi's ASGIMiddleware in InProcessExecutionAPI.transport so that PATH_INFO and SCRIPT_NAME are re-encoded to PEP 3333 form before a2wsgi builds the ASGI scope. Only in-process execution is affected; over a real HTTP connection the ASGI server decodes the path correctly.

closes: #74469

Testing:

  • New unit tests test_in_process_execution_api_handles_non_ascii_path and test_in_process_execution_api_handles_non_ascii_script_name, which fail without this change and pass with it.
  • Ran the reproduction from the issue with dag.test() in Breeze: on main the XCom push fails with UnicodeDecodeError and the Dag run fails; with this change the Dag run succeeds.
  • prek pre-commit and manual stages pass for the changed files.

Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 5.5)

Generated-by: Claude Code (Opus 5.5) following the guidelines

@boring-cyborg boring-cyborg Bot added area:API Airflow's REST/HTTP API area:task-sdk labels Oct 8, 2026
@boring-cyborg

boring-cyborg Bot commented Oct 8, 2026

Copy link
Copy Markdown

Congratulations on your first Pull Request and welcome to the Apache Airflow community! If you have any issues or are unsure about any anything please check our Contributors' Guide
Here are some useful points:

  • Pay attention to the quality of your code (ruff, mypy and type annotations). Our prek-hooks will help you with that.
  • In case of a new feature add useful documentation (in docstrings or in docs/ directory). Adding a new operator? Check this short guide Consider adding an example Dag that shows how users should use it.
  • Consider using Breeze environment for testing locally, it's a heavy docker but it ships with a working Airflow and a lot of integrations.
  • Be patient and persistent. It might take some time to get a review or get the final approval from Committers.
  • Please follow ASF Code of Conduct for all communication including (but not limited to) comments on Pull Requests, Mailing list and Slack.
  • Be sure to read the Airflow Coding style.
  • Always keep your Pull Requests rebased, otherwise your build might fail due to changes not related to your commits.
    Apache Airflow is a community-driven project and together we are making it better 🚀.
    In case of doubts contact the developers at:
    Mailing List: dev@airflow.apache.org
    Slack: https://s.apache.org/airflow-slack

@fat-catTW

Copy link
Copy Markdown
Contributor

Thanks for the the fix.

non-blocking thought: the wrapper also normalizes SCRIPT_NAME, but the new regression test only exercises PATH_INFO. If supporting non-ASCII SCRIPT_NAME is intentional here, could we add a tiny test for that path too?

@eladkal eladkal added this to the Airflow 3.4.0 milestone Oct 9, 2026
@eladkal eladkal added the type:bug-fix Changelog: Bug Fixes label Oct 9, 2026
A task id like "Købsmoms" passes task id validation, but dag.test() failed as
soon as such a task pushed an XCom. In-process execution sends requests
through httpx.WSGITransport, which puts the decoded URL path into PATH_INFO
as a plain str. a2wsgi follows PEP 3333 and expects UTF-8 bytes decoded as
latin-1, so any non-ASCII character in the path raised UnicodeDecodeError or
UnicodeEncodeError and the task failed. Requests over a real HTTP connection
are not affected.
@per-andersen
per-andersen force-pushed the dagtest-fails-for-tasks-whose-task_id-contains-non-ascii-characters branch from 2e6f578 to 57d5a31 Compare October 9, 2026 19:12
@per-andersen

Copy link
Copy Markdown
Author

Thanks for the review!

Updated:

  • Added test_in_process_execution_api_handles_non_ascii_script_name, which sends a non ASCII SCRIPT_NAME through the in-process middleware and checks it arrives intact as the ASGI root_path. It fails without the SCRIPT_NAME re-encoding. Note that InProcessExecutionAPI itself always passes an empty SCRIPT_NAME; the re-encoding matters only if the middleware is mounted under a script name.
  • The fix is now a small ASGIMiddleware subclass instead of a wrapper function, so transport.app remains an ASGIMiddleware. The wrapper broke run_task_instance in tests_common, which reads transport.app.loop (the test_collect_mapped_task_dag_result failure in CI).
  • Rebased onto main after Consolidate in-process Execution API hosting #73327 moved InProcessExecutionAPI to in_process.py; the fix now lives there.

This branch has not been deployed

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

Labels

area:API Airflow's REST/HTTP API area:task-sdk type:bug-fix Changelog: Bug Fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DAG.test() fails for tasks whose task_id contains non ASCII characters

3 participants