From 284a477bb17d55c2e78626873d9917c71335b5f0 Mon Sep 17 00:00:00 2001 From: saerts-gp Date: Thu, 2 Apr 2026 15:11:29 +0200 Subject: [PATCH] fix: guard sensor_d against None in StorageScheduler._prepare Fixes #2084 Context: - StorageScheduler._prepare crashes with AttributeError when a device in the asset tree has no sensor in its flex-model (only power-capacity) - Lines 672 and 740 already guard sensor_d against None, but line 902 was missed Change: - Add 'sensor_d is not None' check before accessing event_resolution - Matches the existing pattern used elsewhere in the same method --- documentation/changelog.rst | 2 +- flexmeasures/data/models/planning/storage.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/changelog.rst b/documentation/changelog.rst index e6e145bedb..9cc9786c14 100644 --- a/documentation/changelog.rst +++ b/documentation/changelog.rst @@ -35,7 +35,7 @@ Infrastructure / Support Bugfixes ----------- - +* Fix ``StorageScheduler`` crash (``AttributeError: 'NoneType' object has no attribute 'event_resolution'``) when scheduling a site whose asset tree contains non-storage devices with only a ``power-capacity`` in their ``flex-model`` (no ``sensor`` key) [see `issue #2084 `_] v0.31.2 | March 18, 2026 ============================ diff --git a/flexmeasures/data/models/planning/storage.py b/flexmeasures/data/models/planning/storage.py index 2a37cd600e..40ed7552df 100644 --- a/flexmeasures/data/models/planning/storage.py +++ b/flexmeasures/data/models/planning/storage.py @@ -899,7 +899,7 @@ def _prepare(self, skip_validation: bool = False) -> tuple: # noqa: C901 device_constraints[d]["efficiency"] = storage_efficiency[d] # Convert efficiency from sensor resolution to scheduling resolution - if sensor_d.event_resolution != timedelta(0): + if sensor_d is not None and sensor_d.event_resolution != timedelta(0): device_constraints[d]["efficiency"] **= ( resolution / sensor_d.event_resolution )