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 f15c37773e4 [v3-3-test] Document HTTP statuses that API routes raise
but never declared (#71011) (#71622)
f15c37773e4 is described below
commit f15c37773e4567949683f1871d19fa4937015778
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Mon Aug 17 11:27:12 2026 +0200
[v3-3-test] Document HTTP statuses that API routes raise but never declared
(#71011) (#71622)
Handlers raise statuses that create_openapi_http_exception_doc never
declares, so
the generated spec — and every client built from it — has no model for a
response
the API really returns.
(cherry picked from commit 7c0b3e66d8cec73c6fc7629cd4f17fbff3025f5a)
Co-authored-by: Jyun-An Chen <[email protected]>
---
.../api_fastapi/core_api/openapi/_private_ui.yaml | 12 ++++++++
.../core_api/openapi/v2-rest-api-generated.yaml | 36 ++++++++++++++++++++++
.../core_api/routes/public/backfills.py | 1 +
.../api_fastapi/core_api/routes/public/dag_run.py | 8 ++++-
.../api_fastapi/core_api/routes/public/dags.py | 1 +
.../api_fastapi/core_api/routes/public/hitl.py | 1 +
.../core_api/routes/public/task_instances.py | 8 ++++-
.../airflow/api_fastapi/core_api/routes/ui/dags.py | 7 ++++-
.../api_fastapi/core_api/routes/ui/dependencies.py | 3 +-
.../ui/openapi-gen/requests/services.gen.ts | 8 +++++
.../airflow/ui/openapi-gen/requests/types.gen.ts | 32 +++++++++++++++++++
11 files changed, 113 insertions(+), 4 deletions(-)
diff --git
a/airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yaml
b/airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yaml
index c1112a747fb..63365d482c3 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yaml
+++ b/airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yaml
@@ -549,6 +549,12 @@ paths:
- $ref: '#/components/schemas/DAGRunLightResponse'
- type: 'null'
title: Response Get Latest Run Info
+ '400':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/HTTPExceptionResponse'
+ description: Bad Request
'404':
content:
application/json:
@@ -597,6 +603,12 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/BaseGraphResponse'
+ '400':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/HTTPExceptionResponse'
+ description: Bad Request
'404':
content:
application/json:
diff --git
a/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml
b/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml
index f55f87f5567..ab0e7a98b9a 100644
---
a/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml
+++
b/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml
@@ -1350,6 +1350,12 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/HTTPExceptionResponse'
+ '400':
+ description: Bad Request
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/HTTPExceptionResponse'
'404':
description: Not Found
content:
@@ -1996,6 +2002,12 @@ paths:
schema:
$ref: '#/components/schemas/HTTPExceptionResponse'
description: Not Found
+ '409':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/HTTPExceptionResponse'
+ description: Conflict
'422':
description: Validation Error
content:
@@ -2629,6 +2641,12 @@ paths:
schema:
$ref: '#/components/schemas/HTTPExceptionResponse'
description: Forbidden
+ '400':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/HTTPExceptionResponse'
+ description: Bad Request
'404':
content:
application/json:
@@ -4115,6 +4133,12 @@ paths:
schema:
$ref: '#/components/schemas/HTTPExceptionResponse'
description: Not Found
+ '409':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/HTTPExceptionResponse'
+ description: Conflict
'422':
content:
application/json:
@@ -8905,6 +8929,12 @@ paths:
schema:
$ref: '#/components/schemas/HTTPExceptionResponse'
description: Forbidden
+ '400':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/HTTPExceptionResponse'
+ description: Bad Request
'404':
content:
application/json:
@@ -10268,6 +10298,12 @@ paths:
schema:
$ref: '#/components/schemas/HTTPExceptionResponse'
description: Forbidden
+ '400':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/HTTPExceptionResponse'
+ description: Bad Request
'404':
content:
application/json:
diff --git
a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/backfills.py
b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/backfills.py
index c4971b883a1..c08adba39fe 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/backfills.py
+++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/backfills.py
@@ -307,6 +307,7 @@ def create_backfill(
path="/dry_run",
responses=create_openapi_http_exception_doc(
[
+ status.HTTP_400_BAD_REQUEST,
status.HTTP_404_NOT_FOUND,
status.HTTP_409_CONFLICT,
status.HTTP_503_SERVICE_UNAVAILABLE,
diff --git
a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/dag_run.py
b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/dag_run.py
index 4b8cdbedb2d..55f6e8da248 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/dag_run.py
+++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/dag_run.py
@@ -149,6 +149,7 @@ def get_dag_run(dag_id: str, dag_run_id: str, session:
SessionDep) -> DAGRunResp
[
status.HTTP_400_BAD_REQUEST,
status.HTTP_404_NOT_FOUND,
+ status.HTTP_409_CONFLICT,
],
),
dependencies=[
@@ -481,7 +482,12 @@ def clear_dag_run_partitions(
@dag_run_router.get(
"",
- responses=create_openapi_http_exception_doc([status.HTTP_404_NOT_FOUND]),
+ responses=create_openapi_http_exception_doc(
+ [
+ status.HTTP_400_BAD_REQUEST,
+ status.HTTP_404_NOT_FOUND,
+ ]
+ ),
dependencies=[Depends(requires_access_dag(method="GET",
access_entity=DagAccessEntity.RUN))],
)
def get_dag_runs(
diff --git
a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/dags.py
b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/dags.py
index 69b6b2932f0..0315a06c7ed 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/dags.py
+++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/dags.py
@@ -449,6 +449,7 @@ def unfavorite_dag(dag_id: str, session: SessionDep, user:
GetUserDep):
[
status.HTTP_400_BAD_REQUEST,
status.HTTP_404_NOT_FOUND,
+ status.HTTP_409_CONFLICT,
HTTP_422_UNPROCESSABLE_CONTENT,
]
),
diff --git
a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/hitl.py
b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/hitl.py
index ccb2c3dd77f..9aa6866aef6 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/hitl.py
+++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/hitl.py
@@ -136,6 +136,7 @@ def _get_task_instance_with_hitl_detail(
task_instance_hitl_path,
responses=create_openapi_http_exception_doc(
[
+ status.HTTP_400_BAD_REQUEST,
status.HTTP_403_FORBIDDEN,
status.HTTP_404_NOT_FOUND,
status.HTTP_409_CONFLICT,
diff --git
a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/task_instances.py
b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/task_instances.py
index 7305e4e89be..a963a47b5ae 100644
---
a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/task_instances.py
+++
b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/task_instances.py
@@ -831,7 +831,13 @@ def get_mapped_task_instance_try_details(
@task_instances_router.post(
"/clearTaskInstances",
- responses=create_openapi_http_exception_doc([status.HTTP_404_NOT_FOUND,
status.HTTP_409_CONFLICT]),
+ responses=create_openapi_http_exception_doc(
+ [
+ status.HTTP_400_BAD_REQUEST,
+ status.HTTP_404_NOT_FOUND,
+ status.HTTP_409_CONFLICT,
+ ]
+ ),
dependencies=[
Depends(action_logging()),
Depends(requires_access_dag(method="PUT",
access_entity=DagAccessEntity.TASK_INSTANCE)),
diff --git a/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/dags.py
b/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/dags.py
index c031d278fa6..a9f0f30a1f5 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/dags.py
+++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/dags.py
@@ -261,7 +261,12 @@ def get_dags(
@dags_router.get(
"/{dag_id}/latest_run",
- responses=create_openapi_http_exception_doc([status.HTTP_404_NOT_FOUND]),
+ responses=create_openapi_http_exception_doc(
+ [
+ status.HTTP_400_BAD_REQUEST,
+ status.HTTP_404_NOT_FOUND,
+ ]
+ ),
dependencies=[Depends(requires_access_dag(method="GET",
access_entity=DagAccessEntity.RUN))],
)
def get_latest_run_info(dag_id: str, session: SessionDep) ->
DAGRunLightResponse | None:
diff --git
a/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/dependencies.py
b/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/dependencies.py
index d09b8acf0e4..f8d1dcbb0f8 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/dependencies.py
+++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/dependencies.py
@@ -41,6 +41,7 @@ dependencies_router = AirflowRouter(tags=["Dependencies"])
"/dependencies",
responses=create_openapi_http_exception_doc(
[
+ status.HTTP_400_BAD_REQUEST,
status.HTTP_404_NOT_FOUND,
]
),
@@ -75,6 +76,6 @@ def get_dependencies(
try:
data = extract_single_connected_component(node_id, data["nodes"],
data["edges"])
except ValueError as e:
- raise HTTPException(404, str(e))
+ raise HTTPException(status.HTTP_404_NOT_FOUND, str(e))
return BaseGraphResponse(**data)
diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts
b/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts
index 6a55c5871c5..8f275ba44f5 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts
@@ -584,6 +584,7 @@ export class BackfillService {
body: data.requestBody,
mediaType: 'application/json',
errors: {
+ 400: 'Bad Request',
401: 'Unauthorized',
403: 'Forbidden',
404: 'Not Found',
@@ -936,6 +937,7 @@ export class DagRunService {
401: 'Unauthorized',
403: 'Forbidden',
404: 'Not Found',
+ 409: 'Conflict',
422: 'Validation Error'
}
});
@@ -1118,6 +1120,7 @@ export class DagRunService {
consuming_asset_pattern: data.consumingAssetPattern
},
errors: {
+ 400: 'Bad Request',
401: 'Unauthorized',
403: 'Forbidden',
404: 'Not Found',
@@ -1768,6 +1771,7 @@ export class DagService {
401: 'Unauthorized',
403: 'Forbidden',
404: 'Not Found',
+ 409: 'Conflict',
422: 'Unprocessable Entity'
}
});
@@ -1959,6 +1963,7 @@ export class DagService {
dag_id: data.dagId
},
errors: {
+ 400: 'Bad Request',
404: 'Not Found',
422: 'Validation Error'
}
@@ -2827,6 +2832,7 @@ export class TaskInstanceService {
body: data.requestBody,
mediaType: 'application/json',
errors: {
+ 400: 'Bad Request',
401: 'Unauthorized',
403: 'Forbidden',
404: 'Not Found',
@@ -3083,6 +3089,7 @@ export class TaskInstanceService {
body: data.requestBody,
mediaType: 'application/json',
errors: {
+ 400: 'Bad Request',
401: 'Unauthorized',
403: 'Forbidden',
404: 'Not Found',
@@ -4653,6 +4660,7 @@ export class DependenciesService {
dependency_type: data.dependencyType
},
errors: {
+ 400: 'Bad Request',
404: 'Not Found',
422: 'Validation Error'
}
diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts
b/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts
index bd476adaf81..6cbad7f571a 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts
@@ -5118,6 +5118,10 @@ export type $OpenApiTs = {
* Successful Response
*/
200: DryRunBackfillCollectionResponse;
+ /**
+ * Bad Request
+ */
+ 400: HTTPExceptionResponse;
/**
* Unauthorized
*/
@@ -5470,6 +5474,10 @@ export type $OpenApiTs = {
* Not Found
*/
404: HTTPExceptionResponse;
+ /**
+ * Conflict
+ */
+ 409: HTTPExceptionResponse;
/**
* Validation Error
*/
@@ -5535,6 +5543,10 @@ export type $OpenApiTs = {
* Successful Response
*/
200: DAGRunCollectionResponse;
+ /**
+ * Bad Request
+ */
+ 400: HTTPExceptionResponse;
/**
* Unauthorized
*/
@@ -6075,6 +6087,10 @@ export type $OpenApiTs = {
* Not Found
*/
404: HTTPExceptionResponse;
+ /**
+ * Conflict
+ */
+ 409: HTTPExceptionResponse;
/**
* Unprocessable Entity
*/
@@ -6217,6 +6233,10 @@ export type $OpenApiTs = {
* Successful Response
*/
200: DAGRunLightResponse | null;
+ /**
+ * Bad Request
+ */
+ 400: HTTPExceptionResponse;
/**
* Not Found
*/
@@ -6726,6 +6746,10 @@ export type $OpenApiTs = {
* Successful Response
*/
200: TaskInstanceCollectionResponse;
+ /**
+ * Bad Request
+ */
+ 400: HTTPExceptionResponse;
/**
* Unauthorized
*/
@@ -6943,6 +6967,10 @@ export type $OpenApiTs = {
* Successful Response
*/
200: HITLDetailResponse;
+ /**
+ * Bad Request
+ */
+ 400: HTTPExceptionResponse;
/**
* Unauthorized
*/
@@ -8195,6 +8223,10 @@ export type $OpenApiTs = {
* Successful Response
*/
200: BaseGraphResponse;
+ /**
+ * Bad Request
+ */
+ 400: HTTPExceptionResponse;
/**
* Not Found
*/