Isolate per-entity failures during number platform setup (#450) - #458
Open
coogle wants to merge 1 commit into
Open
Isolate per-entity failures during number platform setup (#450)#458coogle wants to merge 1 commit into
coogle wants to merge 1 commit into
Conversation
A unit listed in the stored register set that returns no data for a given register raises KeyError inside VictronNumber.__init__, which evaluates value_fn eagerly at construction time. That exception propagates out of async_setup_entry, so a single dead unit removes EVERY number entity across ALL units. The failure is silent and the blast radius is unrelated to the dead device. Observed in the wild: an unpowered SmartShunt (unit 239) not populating battery_power took down number.victron_vebus_activein_currentlimit_237 -- the MultiPlus AC input current limit -- leaving the inverter pinned to a stale 50A limit on a 30A supply for a month with nothing logged above debug. Issue sfstar#450 reports the same defect via evcharger_maxcurrent on slave 41. The sensor platform already tolerates this: it evaluates value_fn lazily inside _handle_coordinator_update and falls back to None. Only numbers evaluate at construction, and only numbers lack a guard -- which is why a dead unit leaves hundreds of working sensors alongside zero working numbers. Two changes, both scoped to number.py: - async_setup_entry skips an individual entity whose register has no data and logs a warning naming the entity and unit, instead of aborting the platform. - native_value returns None if the key disappears after setup (device powered off later) rather than raising on every coordinator update. No behaviour change when all configured units are present and reporting.
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
VictronNumber.__init__evaluatesvalue_fneagerly at construction time:If a unit in the stored register set returns no data for that register, the default
value_fninbase.pyraisesKeyError. There is notry/exceptinnumber.py, so the exception propagates out ofasync_setup_entryand every number entity across every unit fails to be created — not only the one belonging to the device that is actually missing.The failure is silent (nothing logged above
debug), and the blast radius is unrelated to the missing device.Real-world impact
An unpowered SmartShunt (unit 239) stopped populating
battery_power. That removednumber.victron_vebus_activein_currentlimit_237— the MultiPlus AC input current limit — leaving the inverter pinned to a stale 50 A limit on a 30 A supply for a month. Nothing in the log explained it; the control simply readunavailable.Sensors from the same integration, polling the same dead unit, were unaffected: 629 sensors available alongside 0 numbers.
#450 reports the same defect via
evcharger_maxcurrenton slave 41.Why sensors are immune and numbers are not
sensor.pyevaluatesvalue_fnlazily inside_handle_coordinator_update, wrapped intry/except, and falls back toNone.number.pyevaluates at construction and has no guard. That asymmetry is the bug.Change
Two changes, both scoped to
number.py:async_setup_entryskips an individual entity whose register has no data, logging a warning naming the entity and unit, instead of aborting the platform.native_valuereturnsNoneif the key disappears after setup (device powered off later) rather than raising on every coordinator update.No behaviour change when all configured units are present and reporting.
Note on the obvious alternative
Changing
base.py's defaultvalue_fntodict.get()looks like the smaller fix, but it only relocates the failure:native_valuedoesvalue > round(UINT16_MAX / 2), which raisesTypeErroronNone. Keeping the handling innumber.pyconfines the change to the platform that lacks the guard.Testing
Verified on a live install (HA 2025.12, Venus GX, MultiPlus-II 12/3000, MPPT, 2× BLE BMS, one dead unit).
Before: 31 number entities, 0 available. After: all numbers available except the single skipped one, with one log line: