This is an automated email from the ASF dual-hosted git repository.
pierrejeambrun pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new efec6ba3529 Fix `clearTaskInstances` returning 500 instead of 422 on
invalid body (#70237)
efec6ba3529 is described below
commit efec6ba3529aad93115276c18eee59eb08da3877
Author: SreeramaYeshwanthGowd <[email protected]>
AuthorDate: Thu Aug 13 21:59:18 2026 +0530
Fix `clearTaskInstances` returning 500 instead of 422 on invalid body
(#70237)
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.
---
.../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 7166835ce61..cd83cd192aa 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,
)
@@ -239,18 +238,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 0efc3e003e0..7c945edf954 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
@@ -3694,6 +3694,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"),
[