diff --git a/homeassistant/helpers/entity_platform.py b/homeassistant/helpers/entity_platform.py index a57345023c9..9ad5fbd5f61 100644 --- a/homeassistant/helpers/entity_platform.py +++ b/homeassistant/helpers/entity_platform.py @@ -42,6 +42,7 @@ from . import device_registry as dr, entity_registry as er, service, translation from .deprecation import deprecated_function from .entity_registry import EntityRegistry, RegistryEntryDisabler, RegistryEntryHider from .event import async_call_later +from .frame import report_usage from .issue_registry import IssueSeverity, async_create_issue from .typing import UNDEFINED, ConfigType, DiscoveryInfoType, VolDictType, VolSchemaType @@ -822,13 +823,28 @@ class EntityPlatform: # An entity may suggest the entity_id by setting entity_id itself if not hasattr(entity, "internal_integration_suggested_object_id"): if entity.entity_id is not None and not valid_entity_id(entity.entity_id): + if entity.unique_id is not None: + report_usage( + f"sets an invalid entity ID: '{entity.entity_id}'. " + "In most cases, entities should not set entity_id," + " but if they do, it should be a valid entity ID.", + integration_domain=self.platform_name, + breaks_in_ha_version="2027.2.0", + ) + else: + entity.add_to_platform_abort() + raise HomeAssistantError(f"Invalid entity ID: {entity.entity_id}") + try: + entity.internal_integration_suggested_object_id = ( + split_entity_id(entity.entity_id)[1] + if entity.entity_id is not None + else None + ) + except ValueError: entity.add_to_platform_abort() - raise HomeAssistantError(f"Invalid entity ID: {entity.entity_id}") - entity.internal_integration_suggested_object_id = ( - split_entity_id(entity.entity_id)[1] - if entity.entity_id is not None - else None - ) + raise HomeAssistantError( + f"Invalid entity ID: {entity.entity_id}" + ) from None # Get entity_id from unique ID registration if entity.unique_id is not None: diff --git a/tests/helpers/test_entity_platform.py b/tests/helpers/test_entity_platform.py index 09a1b59c6c7..dcc26db5ae7 100644 --- a/tests/helpers/test_entity_platform.py +++ b/tests/helpers/test_entity_platform.py @@ -1967,11 +1967,39 @@ async def test_invalid_entity_id( assert entity.hass is None assert entity.platform is None assert "Invalid entity ID: invalid_entity_id" in caplog.text + # Ensure the valid entity was still added assert entity2.hass is not None assert entity2.platform is not None +async def test_invalid_entity_id_report_usage( + hass: HomeAssistant, caplog: pytest.LogCaptureFixture +) -> None: + """Test that setting an invalid entity_id reports usage.""" + platform = MockEntityPlatform(hass) + entity = MockEntity(entity_id="test_domain.INVALID-ENTITY-ID", unique_id="unique") + + mock_integration = Mock(is_built_in=True, domain="test_platform") + with ( + caplog.at_level(logging.WARNING), + patch( + "homeassistant.helpers.frame.async_get_issue_integration", + return_value=mock_integration, + ), + ): + await platform.async_add_entities([entity]) + + assert ( + "Detected that integration 'test_platform' " + "sets an invalid entity ID: 'test_domain.INVALID-ENTITY-ID'" + ) in caplog.text + + # Ensure the entity was still added + assert entity.hass is not None + assert entity.platform is not None + + class MockBlockingEntity(MockEntity): """Class to mock an entity that will block adding entities."""