From e11e18499eb0dcbad5841812db7a902210daf051 Mon Sep 17 00:00:00 2001 From: andig Date: Sun, 5 Jul 2026 20:49:34 +0200 Subject: [PATCH] fix: return JSON body for message-only 400 aborts The BadRequest errorhandler only returned a JSON body for validation errors (payloads with an 'errors' key) and re-raised message-only api.abort(400, msg) calls, which then rendered as a 400 with an empty body. Clients of e.g. "Invalid data format" / "All time series must have the same length" aborts got no error message. Return error.data for message-only aborts as well. Co-Authored-By: Claude Fable 5 --- src/optimizer/app.py | 3 +++ tests/test_app.py | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/optimizer/app.py b/src/optimizer/app.py index 860d1b406..0efdd660a 100644 --- a/src/optimizer/app.py +++ b/src/optimizer/app.py @@ -45,6 +45,9 @@ def handle_validation_error(error): error.data['details'] = error.data['errors'] del error.data['errors'] return error.data, 400 + elif error.data: + # plain api.abort(400, message) calls carry only a message + return error.data, 400 else: raise error diff --git a/tests/test_app.py b/tests/test_app.py index 0ac0d52cf..eb3488628 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -34,3 +34,25 @@ def test_optimizer(test_case: pathlib.Path): expected_objective_value, rtol=1e-05, atol=1e-08, equal_nan=False), \ f"objective value: {actual_objective_value}, expected was: {expected_objective_value}" + + +def test_abort_returns_json_message(): + # message-only api.abort(400, ...) must return a JSON body, not an empty response + client = app.test_client() + request = { + "batteries": [{ + "s_min": 0, "s_max": 10000, "s_initial": 5000, + "c_min": 0, "c_max": 5000, "d_max": 5000, "p_a": 0.1, + }], + "time_series": { + "dt": [3600, 3600], + "gt": [1000, 1000], + "ft": [0, 0], + "p_N": [0.3, 0.3], + "p_E": [0.1], # length mismatch triggers api.abort(400, message) + }, + } + response = client.post("/optimize/charge-schedule", json=request) + assert response.status_code == 400 + assert response.json is not None + assert "message" in response.json