Skip to content

Commit 27fa4a8

Browse files
CopilotFlix6x
andauthored
api: validate zero-duration posts for non-instantaneous sensors
Agent-Logs-Url: https://github.com/FlexMeasures/flexmeasures/sessions/eb04c29e-a8cf-4f7b-885f-fbe2ec4ef622 Co-authored-by: Flix6x <30658763+Flix6x@users.noreply.github.com>
1 parent e152ede commit 27fa4a8

3 files changed

Lines changed: 30 additions & 3 deletions

File tree

documentation/changelog.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Infrastructure / Support
1414

1515
Bugfixes
1616
-----------
17+
* Return a clear validation error (instead of a server ZeroDivisionError) when posting instantaneous (0-minute) data to non-instantaneous sensors via ``[POST] /sensors/(id)/data`` [see `PR #2116 <https://www.github.com/FlexMeasures/flexmeasures/pull/2116>`_]
1718

1819

1920
v0.32.0 | April 15, 2026

flexmeasures/api/common/schemas/sensor_data.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -329,10 +329,11 @@ def check_resolution_compatibility_of_sensor_data(self, data, **kwargs):
329329
# The event frequency is inferred by assuming sequential, equidistant values within a time interval.
330330
# The event resolution is assumed to be equal to the event frequency.
331331
inferred_resolution = data["duration"] / len(data["values"])
332+
error_message = f"Resolution of {inferred_resolution} is incompatible with the sensor's required resolution of {required_resolution}."
333+
if len(data["values"]) == 1 and inferred_resolution == timedelta(hours=0):
334+
raise ValidationError(error_message)
332335
if inferred_resolution % required_resolution != timedelta(hours=0):
333-
raise ValidationError(
334-
f"Resolution of {inferred_resolution} is incompatible with the sensor's required resolution of {required_resolution}."
335-
)
336+
raise ValidationError(error_message)
336337

337338
@validates_schema
338339
def check_multiple_instantaneous_values(self, data, **kwargs):

flexmeasures/api/v3_0/tests/test_sensor_data.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,31 @@ def test_post_invalid_sensor_data(
187187
)
188188

189189

190+
@pytest.mark.parametrize(
191+
"requesting_user", ["test_supplier_user_4@seita.nl"], indirect=True
192+
)
193+
def test_post_non_instantaneous_sensor_data_with_zero_duration_single_value(
194+
client, setup_api_test_data, requesting_user
195+
):
196+
post_data = make_sensor_data_request_for_gas_sensor(
197+
num_values=1,
198+
duration="PT0M",
199+
unit="m³/h",
200+
)
201+
sensor = setup_api_test_data["some gas sensor"]
202+
203+
response = client.post(
204+
url_for("SensorAPI:post_data", id=sensor.id),
205+
json=post_data,
206+
)
207+
208+
assert response.status_code == 422
209+
assert (
210+
"Resolution of 0:00:00 is incompatible"
211+
in response.json["message"]["combined_sensor_data_description"]["_schema"][0]
212+
)
213+
214+
190215
@pytest.mark.parametrize(
191216
"requesting_user", ["test_supplier_user_4@seita.nl"], indirect=True
192217
)

0 commit comments

Comments
 (0)