From 7f2cd1fe0dcfced793acffc84eb120915ee0b8be Mon Sep 17 00:00:00 2001 From: clydebarrow <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 19 Oct 2026 07:56:34 +1100 Subject: [PATCH] [packet_interface] Reject a duplicate layer type name Every module in layers/ is imported automatically, so two modules registering the same name silently replaced one with the other, in an order decided by pkgutil. Registration now raises, so the mistake is found when the configuration is loaded. Co-Authored-By: Claude Code --- .../components/packet_interface/layers/__init__.py | 4 ++++ tests/unit_tests/test_packet_interface.py | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/esphome/components/packet_interface/layers/__init__.py b/esphome/components/packet_interface/layers/__init__.py index 4f48f3c2b20..1daf62e9db5 100644 --- a/esphome/components/packet_interface/layers/__init__.py +++ b/esphome/components/packet_interface/layers/__init__.py @@ -51,6 +51,10 @@ class LayerKind: """Register a type with its schema.""" def decorator(build: LayerBuilder) -> LayerBuilder: + if name in self.types: + raise ValueError( + f"{self.key} layer type '{name}' is already registered" + ) self.types[name] = LayerType(schema, build) return build diff --git a/tests/unit_tests/test_packet_interface.py b/tests/unit_tests/test_packet_interface.py index 4e184828424..de93673aadf 100644 --- a/tests/unit_tests/test_packet_interface.py +++ b/tests/unit_tests/test_packet_interface.py @@ -103,3 +103,17 @@ def test_registered_type_selectable(setup_core) -> None: assert RELIABILITY.get_type(config).build is build finally: del RELIABILITY.types["test"] + + +def test_duplicate_layer_type_rejected(setup_core) -> None: + """Registering a type under a name already in use is an error, not a silent replacement.""" + + async def build(config: dict, lower: Any) -> Any: + return lower + + RELIABILITY.register("test", schema=cv.Schema({}))(build) + try: + with pytest.raises(ValueError, match="already registered"): + RELIABILITY.register("test", schema=cv.Schema({}))(build) + finally: + del RELIABILITY.types["test"]