Fix discovery crash from quirk removing ZCL attributes - #788
Fix discovery crash from quirk removing ZCL attributes#788TheJulianJES wants to merge 6 commits into
Conversation
Custom v1 quirks that fully override a standard cluster's `attributes` dict (e.g. `attributes = LocalDataCluster.attributes.copy()` on an `OnOff` cluster) produce clusters without standard attribute definitions. `Cluster.is_attribute_unsupported()` raises `KeyError` for unknown attribute names, which propagated out of `Switch._is_supported()` and failed the whole gateway initialization. Check `attributes_by_name` first, like all other `_is_supported` implementations already do. Also fix the check order in `WindowCoveringInversionSwitch._is_supported`, where the existing guard ran after `is_attribute_unsupported()`.
`configure_cluster_configs` aggregates configs from discovered entities before they are filtered by `is_supported()`, so a quirk-replaced cluster missing standard attribute definitions made `find_attribute()` raise `KeyError` during device configuration. Skip such attributes with a debug log, matching how the attribute read path already tolerates them.
A sibling entity's `_server_cluster_config` can list attributes beyond its own `_attribute_name`, which may not exist on a quirk-replaced cluster, making `is_attribute_unsupported()` raise `KeyError` during polling. Check `attributes_by_name` first.
Reproduces the `KeyError: 'on_off'` from home-assistant/core#173265
Avoids registering a v1 quirk in the global `DEVICE_REGISTRY`.
An `AttributeDefs` class inheriting `BaseAttributeDefs` instead of `OnOff.AttributeDefs` replaces the standard attribute definitions the same way the legacy `attributes` dict override does.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## dev #788 +/- ##
=======================================
Coverage 97.41% 97.41%
=======================================
Files 50 50
Lines 10419 10423 +4
=======================================
+ Hits 10150 10154 +4
Misses 269 269 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
There is a branch that covers all four sites this PR touches, plus the one hole they structurally cannot reach — probably worth deciding how to combine them before this gets rebased: dev...zigpy-bot/fix-quirk-missing-attribute-crash Why it came uphome-assistant/core#178581 is the same crash path as the issue this PR targets: This PR as it stands would not fix that one. Quirk entities are constructed with How the two overlap
Both regression tests are on the branch: this PR's What this PR needs on its own
Separate PR, or merged?My suggestion is one PR, because the two changes are not independent: they edit the same four call sites, so whichever lands second has to re-touch those lines. And the relationship is not simply "superset" — once Two ways to do that, whichever you prefer:
On the open question in the description
The branch deliberately takes no position on whether a quirk may drop attribute definitions — it only makes the resulting entity not exist, since reading an attribute the cluster does not define can never do anything but raise. It logs at debug for default discovery, where this is routine for optional attributes, and at warning when a quirk explicitly asked for that entity, which is always an authoring bug. For what it is worth on the "do real quirks do this" question: sweeping all 873 device fixtures in |
DRAFT.
Proposed change
This fixes an issue where a (custom) quirk can remove standard ZCL attributes. Most entity platforms already have guards checking if the attribute even exists, but some do not. This adds them.
Additional information
I'm not sure if this is something we should add – quirks shouldn't misbehave like this. Or are there valid use-cases for deleting ZCL attributes...? But currently, ZHA startup breaks completely when using these custom quirks.
Should address:
This "regression" was introduced with:
AI summary
Issue and fix summary (CLICK TO EXPAND)
Issue
Some custom v1 quirks fully replace a standard cluster's attribute definitions, e.g. the widely used
ts0601_trv_moes.pyfrom jacekk015/zha_quirks does:The resulting
OnOffcluster has noon_off/start_up_on_offattribute definitions.Cluster.is_attribute_unsupported()(andfind_attribute()) raiseKeyErrorfor attribute names without a definition.Since #657,
Switch._is_supported()callscluster.is_attribute_unsupported("on_off")during entity discovery. TheKeyErrorpropagated throughDevice._add_pending_entities()→Gateway.load_devices()→ HA'sasync_setup_entry, so one broken custom quirk prevented the entire ZHA integration from starting (ConfigEntryNotReadyretry loop). Previously, the cluster-handler-based code tolerated these clusters.Affected code paths
Switch._is_supported()was the only_is_supportedimplementation missing theattributes_by_nameguard that all other platforms already had (the crash from the linked issue).WindowCoveringInversionSwitch._is_supported()had the guard, but evaluatedis_attribute_unsupported()first.configure_cluster_configs()calledfind_attribute()unguarded on reporting attributes aggregated from entities not yet filtered byis_supported(), failing on device join/reconfigure.AggregatedClusterPoller.async_update()calledis_attribute_unsupported()unguarded on sibling entities' cluster-config attributes during polling.Fix
Check
attr_name in cluster.attributes_by_namebefore callingis_attribute_unsupported()/find_attribute()at the four sites above, treating attributes without definitions as unsupported (entity not created / reporting skipped with a debug log).A regression test joins a device with a quirks v2 quirk (local registry) that replaces the
OnOffcluster with one whoseAttributeDefsdoes not inherit the standard definitions, reproducing the exactKeyError: 'on_off'from the issue on unfixed code, and asserts device initialization succeeds with no switch entity created.