This is an automated email from the ASF dual-hosted git repository.

eschutho pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git


The following commit(s) were added to refs/heads/master by this push:
     new 0689df740e2 fix(sql-lab): return 400 instead of 500 when stop_query is 
missing client_id (#45521)
0689df740e2 is described below

commit 0689df740e225fd06c391916d4bfd31c8a408221
Author: Elizabeth Thompson <[email protected]>
AuthorDate: Thu Oct 22 15:01:34 2026 -0700

    fix(sql-lab): return 400 instead of 500 when stop_query is missing 
client_id (#45521)
    
    Co-authored-by: Claude Sonnet 5.5 <[email protected]>
---
 docs/static/resources/openapi.json           |  3 +++
 superset/queries/api.py                      |  3 +++
 superset/queries/schemas.py                  |  2 +-
 tests/integration_tests/queries/api_tests.py | 30 ++++++++++++++++++++++++++++
 4 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/docs/static/resources/openapi.json 
b/docs/static/resources/openapi.json
index d6ae235ed60..7baeebd9409 100644
--- a/docs/static/resources/openapi.json
+++ b/docs/static/resources/openapi.json
@@ -11747,6 +11747,9 @@
             "type": "string"
           }
         },
+        "required": [
+          "client_id"
+        ],
         "type": "object"
       },
       "SubjectResponse": {
diff --git a/superset/queries/api.py b/superset/queries/api.py
index 828aded4ac9..235e5426c35 100644
--- a/superset/queries/api.py
+++ b/superset/queries/api.py
@@ -26,6 +26,7 @@ from flask_appbuilder.api import (
     safe,
 )
 from flask_appbuilder.models.sqla.interface import SQLAInterface
+from marshmallow import ValidationError
 
 from superset import db, event_logger
 from superset.common.db_query_status import QueryStatus
@@ -293,5 +294,7 @@ class QueryRestApi(BaseSupersetModelRestApi):
                     query=query.to_dict(),
                 )
             return self.response(200, result="OK")
+        except ValidationError as error:
+            return self.response_400(message=error.messages)
         except SupersetException as ex:
             return self.response(ex.status, message=ex.message)
diff --git a/superset/queries/schemas.py b/superset/queries/schemas.py
index 589dc271910..5ae496e470a 100644
--- a/superset/queries/schemas.py
+++ b/superset/queries/schemas.py
@@ -82,4 +82,4 @@ class StopQuerySchema(Schema):
     Schema for the stop_query API call.
     """
 
-    client_id = fields.String()
+    client_id = fields.String(required=True)
diff --git a/tests/integration_tests/queries/api_tests.py 
b/tests/integration_tests/queries/api_tests.py
index 662c9a175f0..5b6a1e03fa1 100644
--- a/tests/integration_tests/queries/api_tests.py
+++ b/tests/integration_tests/queries/api_tests.py
@@ -18,6 +18,7 @@
 """Unit tests for Superset"""
 
 from datetime import datetime, timedelta
+from unittest import mock
 import random
 import string
 
@@ -32,6 +33,7 @@ from superset.models.core import Database
 from superset.utils.database import get_example_database, get_main_database
 from superset.utils import json
 from superset.models.sql_lab import Query
+from superset.queries.api import QueryRestApi
 
 from tests.integration_tests.base_tests import SupersetTestCase
 from tests.integration_tests.constants import ADMIN_USERNAME, 
GAMMA_SQLLAB_USERNAME
@@ -606,3 +608,31 @@ class TestQueryApi(SupersetTestCase):
         finally:
             db.session.delete(query)
             db.session.commit()
+
+    @mock.patch("superset.queries.api.QueryDAO.stop_query")
+    def test_stop_query_missing_client_id(self, mock_stop_query: mock.Mock) -> 
None:
+        """Return 400 on the first attempt when client_id is missing."""
+        schema = QueryRestApi.stop_query_schema
+        self.login(ADMIN_USERNAME)
+        with mock.patch.object(schema, "load", wraps=schema.load) as mock_load:
+            rv = self.client.post("/api/v1/query/stop", json={})
+
+        assert rv.status_code == 400
+        assert rv.json == {
+            "message": {"client_id": ["Missing data for required field."]}
+        }
+        assert mock_load.call_count == 1
+        mock_stop_query.assert_not_called()
+
+    @mock.patch("superset.queries.api.QueryDAO.stop_query")
+    def test_stop_query_invalid_client_id(self, mock_stop_query: mock.Mock) -> 
None:
+        """Return 400 on the first attempt when client_id has the wrong 
type."""
+        schema = QueryRestApi.stop_query_schema
+        self.login(ADMIN_USERNAME)
+        with mock.patch.object(schema, "load", wraps=schema.load) as mock_load:
+            rv = self.client.post("/api/v1/query/stop", json={"client_id": 
123})
+
+        assert rv.status_code == 400
+        assert rv.json == {"message": {"client_id": ["Not a valid string."]}}
+        assert mock_load.call_count == 1
+        mock_stop_query.assert_not_called()

Reply via email to