fix(state-machine): allow blocked from idle at start_time; never raise from the callback - #337
Open
pluskal wants to merge 1 commit into
Open
fix(state-machine): allow blocked from idle at start_time; never raise from the callback#337pluskal wants to merge 1 commit into
pluskal wants to merge 1 commit into
Conversation
…e from the callback start_time_callback calls blocked()/enable() regardless of current state. When the machine is idle at start_time (HA restarted inside the active window, or an override toggled off while constrained) blocked() raised MachineError, and HA re-fires a failed point-in-time callback endlessly, flooding the log. - add `blocked: idle -> blocked` transition (mirrors the existing sensor_on: idle -> blocked rule) - extract _apply_start_time_transition() and guard it with try/except MachineError, so states with no defined transition log a warning and keep their state instead of raising out of the callback
There was a problem hiding this comment.
Pull request overview
This PR hardens the entity controller state machine against MachineError exceptions triggered from Home Assistant point-in-time callbacks, preventing repeated callback retries and log storms when HA restarts or overrides change state mid-window.
Changes:
- Adds a
blocked: idle -> blockedtransition (guarded byis_block_enabled) sostart_time_callback()can safely move intoblockedwhen alreadyidle. - Extracts start-time transition selection into
_apply_start_time_transition()and wraps it withtry/except MachineErrorto avoid exceptions escaping the scheduled callback.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
45
to
47
| from transitions import Machine | ||
| from transitions.core import MachineError | ||
| from transitions.extensions import HierarchicalMachine as Machine |
Comment on lines
+1272
to
1274
| self._apply_start_time_transition() | ||
| self.do_transition_behaviour(CONF_ON_EXIT_CONSTRAINED) | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
start_time_callback()unconditionally callsblocked()(orenable()) wheneverstart_timeis reached. But the machine is not always inconstrainedat that moment:idleatstart_time.start_time→ alsoidle.danobot defines
blockedonly fromconstrained(and the self/sensor_onrules), soblocked()fromidleraisestransitions.core.MachineError. Because the exception escapes aasync_track_point_in_timecallback, HA re-fires the failed callback endlessly, producing a log/error storm.Fix
blocked: idle -> blockedtransition (guarded byis_block_enabled), mirroring the existingsensor_on: idle -> blockedrule._apply_start_time_transition()and wrap it intry/except MachineError, so any state with no defined transition fromstart_timeis logged and left unchanged instead of raising out of the point-in-time callback. This makes the callback robust to future state/transition gaps as well.from transitions.core import MachineErroradded to imports.Testing
Reproduced the error storm by restarting HA inside the active window; after the fix the controller transitions to
blockedcleanly, and states without a transition log a single warning instead of looping.py_compileclean.