From 0402c19da46f60de67388846d4d0e151e61c7660 Mon Sep 17 00:00:00 2001 From: Deepak Kumar Date: Fri, 22 May 2026 15:38:28 -0700 Subject: [PATCH] UI: Fix /dags/{dag_id}/latest_run returning 500 instead of 400 for dag_id="~" The wrong HTTPException class (http.client.HTTPException, the stdlib base class) was imported in airflow-core/src/airflow/api_fastapi/core_api/routes/ui/dags.py. FastAPI's exception handlers only translate fastapi.HTTPException, so the 400 branch in get_latest_run_info propagated as 500 Internal Server Error. Import HTTPException from fastapi instead and add a regression test. --- .../src/airflow/api_fastapi/core_api/routes/ui/dags.py | 3 +-- .../tests/unit/api_fastapi/core_api/routes/ui/test_dags.py | 7 +++++++ 2 files changed, 8 insertions(+), 2 deletions(-) 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 b517ffe8dee93..dfd3a71d815f5 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 @@ -17,10 +17,9 @@ from __future__ import annotations -from http.client import HTTPException from typing import Annotated -from fastapi import Depends, status +from fastapi import Depends, HTTPException, status from sqlalchemy import and_, func, select from sqlalchemy.orm import defaultload diff --git a/airflow-core/tests/unit/api_fastapi/core_api/routes/ui/test_dags.py b/airflow-core/tests/unit/api_fastapi/core_api/routes/ui/test_dags.py index 8d740b44891a4..47fac78d6291c 100644 --- a/airflow-core/tests/unit/api_fastapi/core_api/routes/ui/test_dags.py +++ b/airflow-core/tests/unit/api_fastapi/core_api/routes/ui/test_dags.py @@ -352,6 +352,13 @@ def test_latest_run_should_response_403(self, unauthorized_test_client): response = unauthorized_test_client.get(f"/dags/{DAG1_ID}/latest_run") assert response.status_code == 403 + def test_latest_run_should_response_400_when_dag_id_is_tilde(self, test_client): + response = test_client.get("/dags/~/latest_run") + assert response.status_code == 400 + assert response.json() == { + "detail": "`~` was supplied as dag_id, but querying multiple dags is not supported." + } + @pytest.mark.parametrize( ("query_params", "expected_dag_count"), [