Compare commits

...
Author SHA1 Message Date
Elizabeth ThompsonandClaude a45f1ddbf5 fix(charts/data): return 400 instead of 500 on reversed date range (SC-118279)
When a user submits a chart data request with a reversed custom date range
(since > until), get_since_until() in superset/utils/date_parser.py raises a
bare ValueError("From date cannot be larger than to date"). This propagates
through ChartDataQueryContextSchema().load() (via its make_query_context
@post_load hook) and out of _create_query_context_from_form(), which only
caught KeyError. The callers catch marshmallow.ValidationError but not
ValueError, so it surfaced as an unhandled 500.

Add a ValueError arm next to the existing KeyError arm in
_create_query_context_from_form(), re-raising as marshmallow.ValidationError so
the API returns a 400. The raised type of get_since_until() is deliberately
left unchanged, since other call sites explicitly catch ValueError today.

Fixes SUPERSET-PYTHON-NA4

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-25 15:10:24 +00:00
3 changed files with 31 additions and 0 deletions
+2
View File
@@ -729,6 +729,8 @@ class ChartDataRestApi(ChartRestApi):
return ChartDataQueryContextSchema().load(form_data)
except KeyError as ex:
raise ValidationError("Request is incorrect") from ex
except ValueError as ex:
raise ValidationError(str(ex)) from ex
def _should_use_streaming(
self, result: dict[Any, Any], form_data: dict[str, Any] | None = None
@@ -363,6 +363,15 @@ class TestPostChartDataApi(BaseTestChartDataApi):
rv = self.post_assert_metric(CHART_DATA_URI, self.query_context_payload, "data")
assert rv.status_code == 400
def test_with_reversed_time_range__400(self):
# A reversed custom date range (since > until) makes get_since_until
# raise a ValueError; the API must convert it to a 400, not a 500.
self.query_context_payload["queries"][0]["time_range"] = (
"2024-01-01T00:00:00 : 2020-01-01T00:00:00"
)
rv = self.post_assert_metric(CHART_DATA_URI, self.query_context_payload, "data")
assert rv.status_code == 400
@pytest.mark.usefixtures("load_birth_names_dashboard_with_slices")
def test_with_invalid_payload__400(self):
invalid_query_context = {"form_data": "NOT VALID JSON"}
@@ -858,3 +858,23 @@ def test_send_chart_response_does_not_double_extension_for_csv_filename() -> Non
content_disposition = response.headers["Content-Disposition"]
assert "my_export.csv.csv" not in content_disposition
assert "my_export.csv" in content_disposition
def test_create_query_context_from_form_converts_value_error_to_400() -> None:
"""
A ValueError raised while loading the query context (e.g. a reversed date
range where since > until) is re-raised as a marshmallow ValidationError so
the API returns a 400 instead of an unhandled 500.
"""
from marshmallow import ValidationError
api = ChartDataRestApi()
message = "From date cannot be larger than to date"
with patch(
"superset.charts.data.api.ChartDataQueryContextSchema.load",
side_effect=ValueError(message),
):
with pytest.raises(ValidationError) as excinfo:
api._create_query_context_from_form({})
assert message in str(excinfo.value)