From b39c83efd23db5190ebf93bf0bc34ac6858af528 Mon Sep 17 00:00:00 2001 From: Will Moss Date: Fri, 27 Mar 2026 11:12:55 -0700 Subject: [PATCH] Handle Oauth2 ImplementationUnavailableError in google (#166647) Co-authored-by: Claude Sonnet 4.6 --- homeassistant/components/google/__init__.py | 17 +++++++++++++---- homeassistant/components/google/strings.json | 5 +++++ tests/components/google/test_init.py | 20 ++++++++++++++++++++ 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/google/__init__.py b/homeassistant/components/google/__init__.py index 0f8be7a52e9..edc7dc50967 100644 --- a/homeassistant/components/google/__init__.py +++ b/homeassistant/components/google/__init__.py @@ -24,6 +24,9 @@ from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady from homeassistant.helpers import config_entry_oauth2_flow, config_validation as cv from homeassistant.helpers.aiohttp_client import async_get_clientsession +from homeassistant.helpers.config_entry_oauth2_flow import ( + ImplementationUnavailableError, +) from homeassistant.helpers.entity import generate_entity_id from .api import ApiAuthImpl, get_feature_access @@ -88,11 +91,17 @@ async def async_setup_entry(hass: HomeAssistant, entry: GoogleConfigEntry) -> bo _LOGGER.error("Configuration error in %s: %s", YAML_DEVICES, str(err)) return False - implementation = ( - await config_entry_oauth2_flow.async_get_config_entry_implementation( - hass, entry + try: + implementation = ( + await config_entry_oauth2_flow.async_get_config_entry_implementation( + hass, entry + ) ) - ) + except ImplementationUnavailableError as err: + raise ConfigEntryNotReady( + translation_domain=DOMAIN, + translation_key="oauth2_implementation_unavailable", + ) from err session = config_entry_oauth2_flow.OAuth2Session(hass, entry, implementation) # Force a token refresh to fix a bug where tokens were persisted with # expires_in (relative time delta) and expires_at (absolute time) swapped. diff --git a/homeassistant/components/google/strings.json b/homeassistant/components/google/strings.json index 2660848f8f2..91fd097ef0d 100644 --- a/homeassistant/components/google/strings.json +++ b/homeassistant/components/google/strings.json @@ -57,6 +57,11 @@ } } }, + "exceptions": { + "oauth2_implementation_unavailable": { + "message": "[%key:common::exceptions::oauth2_implementation_unavailable::message%]" + } + }, "options": { "step": { "init": { diff --git a/tests/components/google/test_init.py b/tests/components/google/test_init.py index 02f9e1b48bd..ee272c54c99 100644 --- a/tests/components/google/test_init.py +++ b/tests/components/google/test_init.py @@ -21,6 +21,9 @@ from homeassistant.config_entries import ConfigEntryState from homeassistant.const import ATTR_FRIENDLY_NAME, STATE_OFF from homeassistant.core import HomeAssistant, State from homeassistant.exceptions import HomeAssistantError, ServiceNotSupported +from homeassistant.helpers.config_entry_oauth2_flow import ( + ImplementationUnavailableError, +) from homeassistant.setup import async_setup_component from homeassistant.util.dt import UTC, utcnow @@ -902,3 +905,20 @@ async def test_remove_entry( assert await hass.config_entries.async_remove(entry.entry_id) assert entry.state is ConfigEntryState.NOT_LOADED + + +async def test_oauth_implementation_not_available( + hass: HomeAssistant, + config_entry: MockConfigEntry, +) -> None: + """Test that unavailable OAuth implementation raises ConfigEntryNotReady.""" + config_entry.add_to_hass(hass) + + with patch( + "homeassistant.helpers.config_entry_oauth2_flow.async_get_config_entry_implementation", + side_effect=ImplementationUnavailableError, + ): + await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + + assert config_entry.state is ConfigEntryState.SETUP_RETRY