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"]