Skip to content

Fix StorageScheduler crash on devices without sensor in flex-model#2085

Open
saerts-gp wants to merge 1 commit intoFlexMeasures:mainfrom
saerts-gp:fix/storage-scheduler-none-sensor-guard
Open

Fix StorageScheduler crash on devices without sensor in flex-model#2085
saerts-gp wants to merge 1 commit intoFlexMeasures:mainfrom
saerts-gp:fix/storage-scheduler-none-sensor-guard

Conversation

@saerts-gp
Copy link
Copy Markdown

Description

  • Fix AttributeError: 'NoneType' object has no attribute 'event_resolution' in StorageScheduler._prepare() when scheduling a site with non-storage devices that only have power-capacity in their flex-model (no sensor key)
  • Added changelog item in documentation/changelog.rst

The existing code at lines 672 and 740 already guards sensor_d against None for get_attribute calls, but the efficiency conversion at line 902 was missed. This one-line fix adds the same sensor_d is not None guard.

Look & Feel

N/A (backend-only fix)

How to test

Schedule a site asset with child assets whose flex_model contains only power-capacity (no sensor key). Before fix: crashes with AttributeError. After fix: completes successfully.

uv run poe test -- tests/data/models/planning/

Further Improvements

None.

Related Items

Closes #2084


Sign-off

  • I agree to contribute to the project under Apache 2 License.
  • To the best of my knowledge, the proposed patch is not based on code under GPL or other license that is incompatible with FlexMeasures

Fixes FlexMeasures#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
@read-the-docs-community
Copy link
Copy Markdown

read-the-docs-community bot commented Apr 2, 2026


# 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):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking of the case where the power sensor of the device is not mentioned in the flex-model of the API trigger message, but the device does have a storage-efficiency defined on the db flex-model.

The storage-efficiency will then become interpreted with respect to the scheduling resolution rather than the device's own power sensor resolution, and requesting the schedule in a different resolution would result in a different interpretation of the storage-efficiency over time.

This is a known shortcoming of our current implementation of the storage-efficiency (see #720), but your solution appears to me it might amplify the problem.

Four possible remedies I see going forward:

  1. Resolve Storage efficiency notation per any time unit. #720
  2. Keep requiring a sensor, but make it possible to define a power sensor in the db flex-model.
  3. If a storage-efficiency is defined in the db flex-model, and the corresponding power sensor is missing, throw a ValidationError.
  4. We document this shortcoming, for instance, in scheduling.rst under the storage-efficiency footnote, and move forward.

I'm assuming your device doesn't have a storage-efficiency, is that correct? Then 3 or 4 seem like a reasonable quick fix to me. Would you agree?

1 and/or 2 are the more long-term solutions, but they for sure require more work and whoever works on them might encounter complications along the way.

@saerts-gp saerts-gp closed this Apr 8, 2026
@nhoening
Copy link
Copy Markdown
Contributor

nhoening commented Apr 8, 2026

@saerts-gp why was this closed - is the underlying problem resolved?

@saerts-gp
Copy link
Copy Markdown
Author

@saerts-gp why was this closed - is the underlying problem resolved?

@nhoening @Flix6x Thanks for the review and apologies for closing without context.

The underlying problem in FlexMeasures is not resolved — the crash at line 902 still exists on main. We worked around it on our application side by ensuring non-storage assets in the tree no longer end up with a flex_model entry that reaches the scheduler — essentially filtering them out before calling compute().

@Flix6x To answer your question: correct, the non-storage devices in our case do not have storage-efficiency defined — they only carry power-capacity. So the efficiency conversion being skipped is a no-op for our scenario.

That said, I agree with your analysis that a blanket None guard could mask the problem for cases where storage-efficiency is defined but the sensor is missing. Although that issue would also be caught by testing, not necessarily crashing. Option 3 (throwing a ValidationError when storage-efficiency is present but sensor is missing) seems like the right balance to me — it protects against the silent misinterpretation you described while still not crashing on the common case of power-capacity-only entries. Again, in our case we would end up with many errors which might not be so good for our logs but we can work around that too.

Happy to update the PR with the approach if you'd like, or feel free to close if you'd prefer to handle it as part of #720.

@Flix6x
Copy link
Copy Markdown
Contributor

Flix6x commented Apr 8, 2026

I'd be glad to accept option 3 in this PR.

@Flix6x Flix6x reopened this Apr 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

StorageScheduler crashes on multi-asset tree with sensor-less flex_model entries

3 participants