Repository: home-assistant/core
File: homeassistant/helpers/update_coordinator.py (Python)

Code before:
            self.config_entry.state
            is not config_entries.ConfigEntryState.SETUP_IN_PROGRESS
        ):
            raise ConfigEntryError(
                f"`async_config_entry_first_refresh` called when config entry state is {self.config_entry.state}, "
                f"but should only be called in state {config_entries.ConfigEntryState.SETUP_IN_PROGRESS}"
            )
        if await self.__wrap_async_setup():
            await self._async_refresh(
                log_failures=False,
                raise_on_auth_failed=True,
                raise_on_entry_error=True,
            )
            if self.last_update_success:
                return
        ex = ConfigEntryNotReady()
        ex.__cause__ = self.last_exception
        raise ex

    async def __wrap_async_setup(self) -> bool:
        """Error handling for _async_setup."""
        try:
            await self._async_setup()

        except (
            OAuth2TokenRequestReauthError,
            OAuth2TokenRequestTransientError,
            OAuth2TokenRequestError,
        ) as err:
            if isinstance(err, OAuth2TokenRequestReauthError):
                # Non-recoverable error
                raise ConfigEntryError from err
            # Recoverable error
            raise ConfigEntryNotReady from err

        except (
            TimeoutError,
            requests.exceptions.Timeout,
            aiohttp.ClientError,
            requests.exceptions.RequestException,
            urllib.error.URLError,
            UpdateFailed,
        ) as err:
            self.last_exception = err

        except (ConfigEntryError, ConfigEntryAuthFailed) as err:
            self.last_exception = err
            self.last_update_success = False
            raise

        except Exception as err:  # pylint: disable=broad-except

Review comment (suggestion):
Make sure to set `last_exception` and `last_update_success`.

Code after:
            is not config_entries.ConfigEntryState.SETUP_IN_PROGRESS
        ):
            raise ConfigEntryError(
                f"`async_config_entry_first_refresh` called when config entry state is {self.config_entry.state}, "
                f"but should only be called in state {config_entries.ConfigEntryState.SETUP_IN_PROGRESS}"
            )
        if await self.__wrap_async_setup():
            await self._async_refresh(
                log_failures=False,
                raise_on_auth_failed=True,
                raise_on_entry_error=True,
            )
            if self.last_update_success:
                return
        ex = ConfigEntryNotReady()
        ex.__cause__ = self.last_exception
        raise ex

    async def __wrap_async_setup(self) -> bool:
        """Error handling for _async_setup."""
        try:
            await self._async_setup()

        except OAuth2TokenRequestError as err:
            self.last_exception = err
            if isinstance(err, OAuth2TokenRequestReauthError):
                self.last_update_success = False
                # Non-recoverable error
                raise ConfigEntryAuthFailed from err

        except (
            TimeoutError,
            requests.exceptions.Timeout,
            aiohttp.ClientError,
            requests.exceptions.RequestException,
            urllib.error.URLError,
            UpdateFailed,
        ) as err:
            self.last_exception = err

        except (ConfigEntryError, ConfigEntryAuthFailed) as err:
            self.last_exception = err
            self.last_update_success = False
            raise

        except Exception as err:  # pylint: disable=broad-except
            self.last_exception = err
            self.logger.exception("Unexpected error fetching %s data", self.name)
        else:
            return True