From 0e8ecd106528995c29bfcd382ad1c2de43349804 Mon Sep 17 00:00:00 2001 From: Andres Ruiz Date: Sat, 2 May 2026 07:52:14 -0400 Subject: [PATCH] Catch additional errors as potentially retryable errors during energy data updates (#169646) --- .../components/waterfurnace/coordinator.py | 7 ++++++- .../waterfurnace/test_statistics.py | 19 ++++++++++++++----- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/waterfurnace/coordinator.py b/homeassistant/components/waterfurnace/coordinator.py index daac61974df6..ec38ab99f460 100644 --- a/homeassistant/components/waterfurnace/coordinator.py +++ b/homeassistant/components/waterfurnace/coordinator.py @@ -13,6 +13,7 @@ from typing import TYPE_CHECKING from waterfurnace.waterfurnace import ( WaterFurnace, WFCredentialError, + WFError, WFException, WFGateway, WFNoDataError, @@ -174,7 +175,7 @@ class WaterFurnaceEnergyCoordinator(DataUpdateCoordinator[None]): frequency="1H", timezone_str=self.hass.config.time_zone, ) - except WFCredentialError: + except WFCredentialError, WFError: try: self.client.login() except WFCredentialError as err: @@ -192,6 +193,10 @@ class WaterFurnaceEnergyCoordinator(DataUpdateCoordinator[None]): raise UpdateFailed( "Authentication failed during energy data fetch" ) from err + except WFError as err: + raise UpdateFailed( + "Error fetching energy data after re-authentication" + ) from err return [ (reading.timestamp, reading.total_power) for reading in data diff --git a/tests/components/waterfurnace/test_statistics.py b/tests/components/waterfurnace/test_statistics.py index 0c891edea40c..de8074acc112 100644 --- a/tests/components/waterfurnace/test_statistics.py +++ b/tests/components/waterfurnace/test_statistics.py @@ -5,7 +5,13 @@ from unittest.mock import Mock, patch from freezegun.api import FrozenDateTimeFactory import pytest -from waterfurnace.waterfurnace import WFCredentialError, WFEnergyData, WFNoDataError +from waterfurnace.waterfurnace import ( + WFCredentialError, + WFEnergyData, + WFError, + WFException, + WFNoDataError, +) from homeassistant.components.recorder import Recorder from homeassistant.components.recorder.models.statistics import StatisticData @@ -225,6 +231,10 @@ async def test_no_data_error_handled_gracefully( assert mock_config_entry.state is ConfigEntryState.LOADED +@pytest.mark.parametrize( + "energy_error", + [WFCredentialError("session expired"), WFError("401 Unauthorized")], +) @pytest.mark.freeze_time(NOW) @pytest.mark.usefixtures("seed_statistics") async def test_login_credential_error_raises_update_failed( @@ -233,16 +243,15 @@ async def test_login_credential_error_raises_update_failed( mock_config_entry: MockConfigEntry, mock_waterfurnace_client: Mock, freezer: FrozenDateTimeFactory, + energy_error: WFException, ) -> None: - """Test that WFCredentialError during energy login raises UpdateFailed.""" + """Test that WFCredentialError/WFError during energy fetch triggers re-login.""" await _setup_integration(hass, mock_config_entry) assert mock_config_entry.state is ConfigEntryState.LOADED # On next poll, get_energy_data fails with expired session, then # re-login also fails with credential error. - mock_waterfurnace_client.get_energy_data.side_effect = WFCredentialError( - "session expired" - ) + mock_waterfurnace_client.get_energy_data.side_effect = energy_error mock_waterfurnace_client.login.side_effect = WFCredentialError("bad creds") await _trigger_energy_poll(hass, freezer)