From 0f62573d8585f97fd101ee981a4b13a5da3e493c Mon Sep 17 00:00:00 2001 From: raman325 <7243222+raman325@users.noreply.github.com> Date: Tue, 17 Feb 2026 11:16:56 -0500 Subject: [PATCH] fix: resolve KeyError when YAML-mode resources lack 'id' field YAML-mode Lovelace resources don't have an 'id' field, only 'url' and 'type'. When users manually added the keymaster resource (as instructed by the warning message), the generator expression crashed on data['id'] before the StopIteration handler could run. Restructured async_register_strategy_resource to check resource existence by URL first (works for both YAML and storage modes), then branch on the result. Fixes #560 Co-Authored-By: Claude Opus 4.6 --- custom_components/keymaster/resources.py | 38 +++++++++++------------- tests/test_resources.py | 19 ++++++++++++ 2 files changed, 37 insertions(+), 20 deletions(-) diff --git a/custom_components/keymaster/resources.py b/custom_components/keymaster/resources.py index 6d7fc760..dc9c4cc6 100644 --- a/custom_components/keymaster/resources.py +++ b/custom_components/keymaster/resources.py @@ -38,30 +38,28 @@ async def async_register_strategy_resource(hass: HomeAssistant) -> None: _LOGGER.debug("Manually loaded resources") resources.loaded = True - try: - res_id = next( - data[CONF_ID] for data in resources.async_items() if data[CONF_URL] == STRATEGY_PATH - ) - except StopIteration: - if isinstance(resources, ResourceYAMLCollection): - _LOGGER.warning( - "Strategy module can't automatically be registered because this " - "Home Assistant instance is running in YAML mode for resources. " - "Please add a new entry in the list under the resources key in " - 'the lovelace section of your config as follows:\n - url: "%s"' - "\n type: module", - STRATEGY_PATH, - ) - return + already_registered = any(data[CONF_URL] == STRATEGY_PATH for data in resources.async_items()) + + if already_registered: + _LOGGER.debug("Strategy module already registered") + return - data = await resources.async_create_item( - {CONF_RESOURCE_TYPE_WS: "module", CONF_URL: STRATEGY_PATH} + if isinstance(resources, ResourceYAMLCollection): + _LOGGER.warning( + "Strategy module can't automatically be registered because this " + "Home Assistant instance is running in YAML mode for resources. " + "Please add a new entry in the list under the resources key in " + 'the lovelace section of your config as follows:\n - url: "%s"' + "\n type: module", + STRATEGY_PATH, ) - _LOGGER.debug("Registered strategy module (resource ID %s)", data[CONF_ID]) - hass.data[DOMAIN]["resources"] = True return - _LOGGER.debug("Strategy module already registered with resource ID %s", res_id) + data = await resources.async_create_item( + {CONF_RESOURCE_TYPE_WS: "module", CONF_URL: STRATEGY_PATH} + ) + _LOGGER.debug("Registered strategy module (resource ID %s)", data[CONF_ID]) + hass.data[DOMAIN]["resources"] = True async def async_cleanup_strategy_resource(hass: HomeAssistant, hass_data: dict[str, Any]) -> None: diff --git a/tests/test_resources.py b/tests/test_resources.py index 9266b738..a4ab4cb9 100644 --- a/tests/test_resources.py +++ b/tests/test_resources.py @@ -120,6 +120,25 @@ async def test_register_strategy_resource_yaml_mode_warning( assert STRATEGY_PATH in caplog.text +async def test_register_strategy_resource_yaml_mode_already_exists( + hass: HomeAssistant, mock_yaml_resources, caplog +): + """Test no error when resource already exists in YAML mode (no 'id' field).""" + mock_yaml_resources.async_items.return_value = [ + {"url": "/local/other.js", "type": "module"}, + {"url": STRATEGY_PATH, "type": "module"}, + ] + hass.data[LOVELACE_DOMAIN] = MagicMock() + hass.data[LOVELACE_DOMAIN].resources = mock_yaml_resources + hass.data[DOMAIN] = {} + + with caplog.at_level(logging.DEBUG): + await async_register_strategy_resource(hass) + + assert "already registered" in caplog.text + assert "YAML mode" not in caplog.text + + async def test_register_strategy_resource_no_resources(hass: HomeAssistant): """Test registering when no resources available.""" # No lovelace domain