This is an automated email from the ASF dual-hosted git repository.
pierrejeambrun pushed a commit to branch v3-3-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/v3-3-test by this push:
new 600c8f768c9 [v3-3-test] Fix `clearTaskInstances` returning 500 instead
of 422 on invalid body (#70237) (#71559)
600c8f768c9 is described below
commit 600c8f768c9211c12806fa795d1c6bf85b428a1b
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Fri Aug 14 14:51:49 2026 +0200
[v3-3-test] Fix `clearTaskInstances` returning 500 instead of 422 on
invalid body (#70237) (#71559)
The ClearTaskInstancesBody validator raised pydantic.ValidationError with a
string argument for its invalid-input branches. In Pydantic v2 that
constructor
call raises TypeError, which the core API has no handler for, so an invalid
request body surfaced as 500 Internal Server Error instead of a 422. Raising
ValueError lets Pydantic report the problem as a normal 422, matching the
sibling PatchTaskInstanceBody validator in the same file.
(cherry picked from commit efec6ba3529aad93115276c18eee59eb08da3877)
Co-authored-by: SreeramaYeshwanthGowd <[email protected]>
---
.../core_api/datamodels/task_instances.py | 13 ++++-----
.../core_api/routes/public/test_task_instances.py | 34 ++++++++++++++++++++++
2 files changed, 40 insertions(+), 7 deletions(-)
diff --git
a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/task_instances.py
b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/task_instances.py
index 85e14bc3baf..7a56e616463 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/task_instances.py
+++ b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/task_instances.py
@@ -30,7 +30,6 @@ from pydantic import (
NonNegativeInt,
StringConstraints,
Tag,
- ValidationError,
field_validator,
model_validator,
)
@@ -232,18 +231,18 @@ class ClearTaskInstancesBody(StrictBaseModel):
def validate_model(cls, data: Any) -> Any:
"""Validate clear task instance form."""
if data.get("only_failed") and data.get("only_running"):
- raise ValidationError("only_failed and only_running both are set
to True")
+ raise ValueError("only_failed and only_running both are set to
True")
if data.get("start_date") and data.get("end_date"):
if data.get("start_date") > data.get("end_date"):
- raise ValidationError("end_date is sooner than start_date")
+ raise ValueError("end_date is sooner than start_date")
if data.get("start_date") and data.get("end_date") and
data.get("dag_run_id"):
- raise ValidationError("Exactly one of dag_run_id or (start_date
and end_date) must be provided")
+ raise ValueError("Exactly one of dag_run_id or (start_date and
end_date) must be provided")
if data.get("start_date") and data.get("dag_run_id"):
- raise ValidationError("Exactly one of dag_run_id or start_date
must be provided")
+ raise ValueError("Exactly one of dag_run_id or start_date must be
provided")
if data.get("end_date") and data.get("dag_run_id"):
- raise ValidationError("Exactly one of dag_run_id or end_date must
be provided")
+ raise ValueError("Exactly one of dag_run_id or end_date must be
provided")
if isinstance(data.get("task_ids"), list) and
len(data.get("task_ids")) < 1:
- raise ValidationError("task_ids list should have at least 1
element.")
+ raise ValueError("task_ids list should have at least 1 element.")
return data
diff --git
a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_task_instances.py
b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_task_instances.py
index ae3a8388fea..20799635046 100644
---
a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_task_instances.py
+++
b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_task_instances.py
@@ -3556,6 +3556,40 @@ class
TestPostClearTaskInstances(TestTaskInstanceEndpoint):
)
assert response.status_code == 403
+ @pytest.mark.parametrize(
+ "payload",
+ [
+ pytest.param(
+ {"only_failed": True, "only_running": True},
+ id="only_failed_and_only_running",
+ ),
+ pytest.param(
+ {"start_date": "2024-01-02T00:00:00Z", "end_date":
"2024-01-01T00:00:00Z"},
+ id="start_date_after_end_date",
+ ),
+ pytest.param(
+ {
+ "start_date": "2024-01-01T00:00:00Z",
+ "end_date": "2024-01-02T00:00:00Z",
+ "dag_run_id": "run_1",
+ },
+ id="dag_run_id_with_start_and_end_date",
+ ),
+ pytest.param(
+ {"start_date": "2024-01-01T00:00:00Z", "dag_run_id": "run_1"},
+ id="dag_run_id_with_start_date",
+ ),
+ pytest.param(
+ {"end_date": "2024-01-01T00:00:00Z", "dag_run_id": "run_1"},
+ id="dag_run_id_with_end_date",
+ ),
+ pytest.param({"task_ids": []}, id="empty_task_ids"),
+ ],
+ )
+ def test_should_respond_422_on_invalid_body(self, test_client, payload):
+ response =
test_client.post("/dags/example_python_operator/clearTaskInstances",
json=payload)
+ assert response.status_code == 422
+
@pytest.mark.parametrize(
("main_dag", "task_instances", "request_dag", "payload",
"expected_ti"),
[