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

Code before:
            start = monotonic()

        auth_failed = False
        previous_update_success = self.last_update_success
        previous_data = self.data

        try:
            self.data = await self._async_update_data()

        except (TimeoutError, requests.exceptions.Timeout) as err:
            self.last_exception = err
            if self.last_update_success:
                if log_failures:
                    self.logger.error("Timeout fetching %s data", self.name)
                self.last_update_success = False

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

        except (aiohttp.ClientError, requests.exceptions.RequestException) as err:
            self.last_exception = err
            if self.last_update_success:
                if log_failures:
                    self.logger.error("Error requesting %s data: %s", self.name, err)
                self.last_update_success = False

        except urllib.error.URLError as err:
            self.last_exception = err
            if self.last_update_success:
                if log_failures:
                    if err.reason == "timed out":
                        self.logger.error("Timeout fetching %s data", self.name)
                    else:
                        self.logger.error(
                            "Error requesting %s data: %s", self.name, err
                        )
                self.last_update_success = False

        except UpdateFailed as err:
            self.last_exception = err
            # We can only honor a retry_after, after the config entry has been set up
            # Basically meaning that the retry after can't be used when coming
            # from an async_config_entry_first_refresh

Review comment (bug):
I think this will be raised on line 352 if it's the first refresh called during config entry setup. I think we should do the same thing as for `UpdateFailed`.

Code after:

        try:
            self.data = await self._async_update_data()

        except (TimeoutError, requests.exceptions.Timeout) as err:
            self.last_exception = err
            if self.last_update_success:
                if log_failures:
                    self.logger.error("Timeout fetching %s data", self.name)
                self.last_update_success = False

        except (OAuth2TokenRequestError,) as err:
            self.last_exception = err
            if isinstance(err, OAuth2TokenRequestReauthError):
                # Non-recoverable error
                auth_failed = True
                if self.last_update_success:
                    if log_failures:
                        self.logger.error(
                            "Authentication failed while fetching %s data: %s",
                            self.name,
                            err,
                        )
                    self.last_update_success = False
                if raise_on_auth_failed:
                    raise ConfigEntryAuthFailed from err

                if self.config_entry:
                    self.config_entry.async_start_reauth(self.hass)
                return

            # Recoverable error
            if self.last_update_success:
                if log_failures:
                    self.logger.error("Error fetching %s data: %s", self.name, err)
                self.last_update_success = False

        except (aiohttp.ClientError, requests.exceptions.RequestException) as err:
            self.last_exception = err
            if self.last_update_success:
                if log_failures:
                    self.logger.error("Error requesting %s data: %s", self.name, err)
                self.last_update_success = False

        except urllib.error.URLError as err:
            self.last_exception = err
            if self.last_update_success:
                if log_failures:
                    if err.reason == "timed out":
                        self.logger.error("Timeout fetching %s data", self.name)
                    else: