potiuk opened a new pull request, #70889:
URL: https://github.com/apache/airflow/pull/70889
The backfill routes declare `backfill_id: NonNegativeInt`, but
`requires_access_backfill` parsed the raw path value with `int()` and
swallowed
the failure. Those two parsers do not agree.
### The divergence
| supplied `backfill_id` | `NonNegativeInt` (the handler) | `int()` (the
dependency) |
|---|---|---|
| `"42"` | 42 | 42 |
| `"42.0"` | **42** | ValueError |
| `"42.00"` | **42** | ValueError |
| `"42."`, `"42e0"`, `"42.5"`, `"0x2a"` | rejected | ValueError |
pydantic's lax mode accepts the two decimal spellings and coerces them to an
int; `int()` rejects them.
FastAPI resolves route dependencies *before* the endpoint's own parameter
validation, so for those spellings the dependency's parse failed, it left the
Dag unresolved, and the request went on to be served by the handler against
backfill 42. The dependency and the handler disagreed about which backfill --
and therefore which Dag -- the request concerned.
### Approach
Parse with the same `TypeAdapter(NonNegativeInt)` the routes declare, so the
two cannot diverge by construction. The adapter is module-level and named, so
the coupling to the route signature is explicit rather than re-derived.
This deliberately does **not** introduce a stricter parser. An earlier
revision
used `int()` with an explicit 400, which changed the public API contract: a
malformed path value such as `/backfills/invalid_id` previously produced
FastAPI's structured **422** (`loc: ["path", "backfill_id"]`), and a 400 from
the dependency preempted it. Five existing route tests caught that. Matching
the declared type keeps every existing status code and body shape intact --
values both parsers reject still yield the handler's 422, and an unknown
backfill still yields each route's own 404 wording.
### Test plan
- [x]
`test_requires_access_backfill_authorizes_the_backfill_the_handler_will_act_on`
-- parametrized over `42`, `42.0`, `42.00`; asserts the Dag comes from
the
resolved backfill and not from a value supplied on the request
- [x] Verified against unmodified code: `42.0` and `42.00` **fail**, `42`
passes --
so the test pins the divergence and not the plumbing
- [x] `airflow-core/tests/unit/api_fastapi/core_api/test_security.py` -- 111
passed
- [x]
`airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_backfills.py`
-- 63 passed, including the four `test_invalid_id` 422 cases and
`test_no_exist`
- [x] `ruff check` / `ruff format` clean
##### Was generative AI tooling used to co-author this PR?
- [X] Yes — Claude Opus 5 (1M context)
Generated-by: Claude Opus 5 (1M context) following the guidelines at
https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]