Skip to content

MFA login error after updating HomeAssistant to 2026.3.2 #420

Description

@pejotigrek

Describe the bug
after updating HomeAssistant to 2026.3.2, I saw that integration started to flood log file with errors. I've got two accounts connected, one with MFA, one without. only the MFA is affected. I tried to reconfigure it but got an error while entering MFA codes.

To Reproduce
Steps to reproduce the behavior when adding configuration [logs below, in additional content]:

  1. Go to 'Configuration', 'Devices & Services'
  2. Click on '+ Add' to add 'Garmin Connect'
  3. Enter login + password of account with two-factor-authentication
  4. Wait for MFA code, enter when asked for
  5. See error

Steps to reproduce the behavior with existing configuration [another logs below, in additional content]

  1. Go to 'Configuration', 'Devices & Services'
  2. Click on 'Garmin Connect' integration
  3. See errors on entity with MFA

Expected behavior
MFA secured account working as usual - with no problems.

Screenshots
Error while reconfiguring/adding account with MFA:

Image

Error with existing entity:

Image

Desktop (please complete the following information):

  • OS: Windows 11
  • Browser Chrome
  • Version 146.0.7680.80 (Official) (64-bit)

Smartphone (please complete the following information):

  • Device: Google Pixel 8 Pro
  • OS: Android 16 (CP1A.260305.018)
  • Browser Chrome / HA Companion APP
  • Version Chrome 146.0.7680.119 / HA Companion APP 2026.3.2-full (20802)

Additional context
Log errors shown while adding account with MFA:

2026-03-17 10:09:05.870 ERROR (MainThread) [aiohttp.server] Error handling request from 172.30.33.3
Traceback (most recent call last):
  File "/usr/local/lib/python3.14/site-packages/aiohttp/web_protocol.py", line 510, in _handle_request
    resp = await request_handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.14/site-packages/aiohttp/web_app.py", line 569, in _handle
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.14/site-packages/aiohttp/web_middlewares.py", line 117, in impl
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/security_filter.py", line 92, in security_filter_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/forwarded.py", line 214, in forwarded_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/request_context.py", line 26, in request_context_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/ban.py", line 86, in ban_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/auth.py", line 242, in auth_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/headers.py", line 41, in headers_middleware
    response = await handler(request)
               ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/http.py", line 73, in handle
    result = await handler(request, **request.match_info)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/decorators.py", line 83, in with_admin
    return await func(self, request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/config/config_entries.py", line 234, in post
    return await super().post(request, flow_id)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/data_validator.py", line 74, in wrapper
    return await method(view, request, data, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/data_entry_flow.py", line 121, in post
    result = await self._flow_mgr.async_configure(flow_id, data)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 336, in async_configure
    result = await self._async_configure(flow_id, user_input)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/config_entries.py", line 1536, in _async_configure
    return await super()._async_configure(flow_id, user_input)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 383, in _async_configure
    result = await self._async_handle_step(
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        flow, cur_step["step_id"], user_input
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 483, in _async_handle_step
    result: _FlowResultT = await getattr(flow, method)(user_input)
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/garmin_connect/config_flow.py", line 177, in async_step_mfa
    return await self._async_garmin_connect_mfa_login()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/garmin_connect/config_flow.py", line 109, in _async_garmin_connect_mfa_login
    await self.hass.async_add_executor_job(self._api.resume_login, self._login_result2, self._mfa_code)
  File "/usr/local/lib/python3.14/concurrent/futures/thread.py", line 86, in run
    result = ctx.run(self.task)
  File "/usr/local/lib/python3.14/concurrent/futures/thread.py", line 73, in run
    return fn(*args, **kwargs)
  File "/usr/local/lib/python3.14/site-packages/garminconnect/__init__.py", line 588, in resume_login
    result1, result2 = self.garth.resume_login(client_state, mfa_code)
                       ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.14/site-packages/garth/http.py", line 209, in resume_login
    self.oauth1_token, self.oauth2_token = sso.resume_login(
                                           ~~~~~~~~~~~~~~~~^
        *args, **kwargs
        ^^^^^^^^^^^^^^^
    )
    ^
  File "/usr/local/lib/python3.14/site-packages/garth/sso.py", line 247, in resume_login
    return _complete_login(client)
  File "/usr/local/lib/python3.14/site-packages/garth/sso.py", line 267, in _complete_login
    oauth1 = get_oauth1_token(ticket, client)
  File "/usr/local/lib/python3.14/site-packages/garth/sso.py", line 158, in get_oauth1_token
    resp.raise_for_status()
    ~~~~~~~~~~~~~~~~~~~~~^^
  File "/usr/local/lib/python3.14/site-packages/requests/models.py", line 1026, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 401 Client Error: Unauthorized for url: https://connectapi.garmin.com/oauth-service/oauth/preauthorized?ticket=ST-0633056-ID1fl5AnLGQP5sSCbWOd-cas&login-url=https://sso.garmin.com/sso/embed&accepts-mfa-tokens=true

Log errors with existing MFA secured account - flooding logfile while trying to automatically (re)login:

2026-03-17 09:51:48.415 ERROR (SyncWorker_2) [garminconnect] Login failed: 403 Client Error: Forbidden for url: https://connectapi.garmin.com/oauth-service/oauth/exchange/user/2.0 (status=403)
Traceback (most recent call last):
  File "/usr/local/lib/python3.14/site-packages/garminconnect/__init__.py", line 506, in login
    if not getattr(self.garth, "profile", None):
           ~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.14/site-packages/garth/http.py", line 143, in profile
    return self.user_profile
           ^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.14/site-packages/garth/http.py", line 133, in user_profile
    self._user_profile = self.connectapi(
                         ~~~~~~~~~~~~~~~^
        "/userprofile-service/socialProfile"
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/usr/local/lib/python3.14/site-packages/garth/http.py", line 227, in connectapi
    resp = self.request(method, "connectapi", path, api=True, **kwargs)
  File "/usr/local/lib/python3.14/site-packages/garth/http.py", line 172, in request
    self.refresh_oauth2()
    ~~~~~~~~~~~~~~~~~~~^^
  File "/usr/local/lib/python3.14/site-packages/garth/http.py", line 220, in refresh_oauth2
    self.oauth2_token = sso.exchange(self.oauth1_token, self)
                        ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.14/site-packages/garth/sso.py", line 183, in exchange
    resp.raise_for_status()
    ~~~~~~~~~~~~~~~~~~~~~^^
  File "/usr/local/lib/python3.14/site-packages/requests/models.py", line 1026, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 403 Client Error: Forbidden for url: https://connectapi.garmin.com/oauth-service/oauth/exchange/user/2.0
2026-03-17 09:51:48.420 ERROR (MainThread) [custom_components.garmin_connect] Connection error occurred during Garmin Connect login request: Login failed: 403 Client Error: Forbidden for url: https://connectapi.garmin.com/oauth-service/oauth/exchange/user/2.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions