From f80669b7f13fb913e7a93927be19bfd94f3e6312 Mon Sep 17 00:00:00 2001 From: Martin Hjelmare Date: Mon, 17 Aug 2026 13:18:53 +0200 Subject: [PATCH] Handle exception from refresh token callback --- test/test_realtime.py | 26 ++++++++++++++++++++++++++ tibber/__init__.py | 6 +++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/test/test_realtime.py b/test/test_realtime.py index fc4b285..2cb2c26 100644 --- a/test/test_realtime.py +++ b/test/test_realtime.py @@ -15,6 +15,7 @@ from gql.transport.exceptions import TransportConnectionFailed, TransportError from websockets.asyncio.connection import State +import tibber from tibber.exceptions import SubscriptionEndpointMissingError, WebsocketReconnectedError, WebsocketTransportError from tibber.realtime import TibberRT, TibberWebsocketsTransport @@ -205,6 +206,31 @@ async def test_reconnect_rebuilds_transport_when_token_unchanged( await tibber_rt.disconnect() +async def test_reconnect_completes_when_refresh_token_callback_raises( + mock_client: MagicMock, +) -> None: + """A raising refresh_access_token callback must not abort the reconnect flow.""" + tibber_connection = tibber.Tibber( + access_token="test_token", + websession=MagicMock(), + user_agent="test_agent", + refresh_access_token=AsyncMock(side_effect=Exception), + ) + await tibber_connection.realtime.set_subscription_endpoint("wss://test.endpoint") + + await tibber_connection.realtime.connect() + first_transport = mock_client.transport + mock_client.transport.adapter.websocket = MagicMock(state=State.CLOSED) + + await tibber_connection.realtime.reconnect() + + mock_client.close_async.assert_awaited_once() + assert mock_client.transport is not first_transport + assert tibber_connection.realtime.subscription_running is True + + await tibber_connection.realtime.disconnect() + + async def test_transport_close_times_out_on_hanging_wait_closed( monkeypatch: pytest.MonkeyPatch, ) -> None: diff --git a/tibber/__init__.py b/tibber/__init__.py index 4e85712..95e64b0 100644 --- a/tibber/__init__.py +++ b/tibber/__init__.py @@ -96,7 +96,11 @@ async def _refresh_access_token_for_reconnect(self) -> str | None: if self._refresh_access_token is None: return None - access_token = await self._refresh_access_token() + try: + access_token = await self._refresh_access_token() + except Exception: + _LOGGER.exception("Error refreshing access token") + return None if access_token is not None and access_token != self._access_token: _LOGGER.debug("Updating access token") self._access_token = access_token