diff --git a/homeassistant/components/music_assistant/__init__.py b/homeassistant/components/music_assistant/__init__.py index dd9e64a92d1..c0d56abba2b 100644 --- a/homeassistant/components/music_assistant/__init__.py +++ b/homeassistant/components/music_assistant/__init__.py @@ -27,7 +27,11 @@ from music_assistant_models.player import Player from homeassistant.config_entries import ConfigEntry, ConfigEntryState from homeassistant.const import CONF_URL, EVENT_HOMEASSISTANT_STOP, Platform from homeassistant.core import Event, HomeAssistant -from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady +from homeassistant.exceptions import ( + ConfigEntryAuthFailed, + ConfigEntryError, + ConfigEntryNotReady, +) from homeassistant.helpers import config_validation as cv, device_registry as dr from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.issue_registry import ( @@ -101,6 +105,15 @@ async def async_setup_entry( # noqa: C901 ) raise ConfigEntryNotReady(f"Invalid server version: {err}") from err except (AuthenticationRequired, AuthenticationFailed, InvalidToken) as err: + assert mass.server_info is not None + # Users cannot reauthenticate when running as Home Assistant addon, + # so raising ConfigEntryAuthFailed in that case would be incorrect. + # Instead we should wait until the addon discovery is completed, + # as that will set up authentication and reload the entry automatically. + if mass.server_info.homeassistant_addon: + raise ConfigEntryError( + "Authentication failed, addon discovery not completed yet" + ) from err raise ConfigEntryAuthFailed( f"Authentication failed for {mass_url}: {err}" ) from err diff --git a/homeassistant/components/music_assistant/config_flow.py b/homeassistant/components/music_assistant/config_flow.py index 226a4dda28f..c03ae85fd04 100644 --- a/homeassistant/components/music_assistant/config_flow.py +++ b/homeassistant/components/music_assistant/config_flow.py @@ -179,6 +179,7 @@ class MusicAssistantConfigFlow(ConfigFlow, domain=DOMAIN): ConfigEntryState.LOADED, ConfigEntryState.SETUP_ERROR, ConfigEntryState.SETUP_RETRY, + ConfigEntryState.SETUP_IN_PROGRESS, ): self.hass.config_entries.async_schedule_reload(entry.entry_id) diff --git a/tests/components/music_assistant/test_init.py b/tests/components/music_assistant/test_init.py index 2126aa7cdff..2c7ad8a0a74 100644 --- a/tests/components/music_assistant/test_init.py +++ b/tests/components/music_assistant/test_init.py @@ -164,7 +164,6 @@ async def test_authentication_required_triggers_reauth( music_assistant_client: MagicMock, ) -> None: """Test that AuthenticationRequired exception triggers reauth flow.""" - # Create a config entry config_entry = MockConfigEntry( domain=DOMAIN, title="Music Assistant", @@ -173,19 +172,44 @@ async def test_authentication_required_triggers_reauth( ) config_entry.add_to_hass(hass) - # Mock the client to raise AuthenticationRequired during connect music_assistant_client.connect.side_effect = AuthenticationRequired( "Authentication required" ) - # Try to set up the integration await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() - # Verify the entry is in SETUP_ERROR state (auth failed) assert config_entry.state is ConfigEntryState.SETUP_ERROR - # Verify a reauth repair issue was created issue_reg = ir.async_get(hass) issue_id = f"config_entry_reauth_{DOMAIN}_{config_entry.entry_id}" assert issue_reg.async_get_issue("homeassistant", issue_id) + + +async def test_authentication_required_addon_no_reauth( + hass: HomeAssistant, + music_assistant_client: MagicMock, +) -> None: + """Test that AuthenticationRequired exception does not trigger reauth for addon.""" + config_entry = MockConfigEntry( + domain=DOMAIN, + title="Music Assistant", + data={"url": "http://localhost:8095", "token": "old_token"}, + unique_id="test_server_id", + ) + config_entry.add_to_hass(hass) + + music_assistant_client.server_info.homeassistant_addon = True + + music_assistant_client.connect.side_effect = AuthenticationRequired( + "Authentication required" + ) + + await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + + assert config_entry.state is ConfigEntryState.SETUP_ERROR + + issue_reg = ir.async_get(hass) + issue_id = f"config_entry_reauth_{DOMAIN}_{config_entry.entry_id}" + assert issue_reg.async_get_issue("homeassistant", issue_id) is None