{"record":{"id":"2b6c657c0cb767cf","repo":"home-assistant/core","slug":"error","errorCode":null,"errorMessage":"{error}","messagePattern":"\\{error\\}","errorType":"exception","errorClass":"UpdateFailed","httpStatus":null,"severity":"error","filePath":"homeassistant/components/aemet/coordinator.py","lineNumber":70,"sourceCode":"        \"\"\"Initialize coordinator.\"\"\"\n        self.aemet = aemet\n\n        super().__init__(\n            hass,\n            _LOGGER,\n            config_entry=entry,\n            name=DOMAIN,\n            update_interval=WEATHER_UPDATE_INTERVAL,\n        )\n\n    @override\n    async def _async_update_data(self) -> dict[str, Any]:\n        \"\"\"Update coordinator data.\"\"\"\n        async with timeout(API_TIMEOUT):\n            try:\n                await self.aemet.update()\n            except AemetError as error:\n                raise UpdateFailed(error) from error\n\n        data = self.aemet.data()\n\n        return {\n            \"forecast\": {\n                AOD_FORECAST_DAILY: self.aemet_forecast(data, AOD_FORECAST_DAILY),\n                AOD_FORECAST_HOURLY: self.aemet_forecast(data, AOD_FORECAST_HOURLY),\n            },\n            \"lib\": data,\n        }\n\n    def aemet_forecast(\n        self,\n        data: dict[str, Any],\n        forecast_mode: str,\n    ) -> list[Forecast]:\n        \"\"\"Return the forecast array.\"\"\"\n        forecasts = dict_nested_value(data, [AOD_TOWN, forecast_mode, AOD_FORECAST])","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/home-assistant/core/blob/58a3fdb3ea0538617f0a07efcfba6294de64fd59/homeassistant/components/aemet/coordinator.py#L52-L88","documentation":"UpdateFailed raised by WeatherUpdateCoordinator._async_update_data when self.aemet.update() raises AemetError inside a timeout(API_TIMEOUT) window. This is the polling failure path for the AEMET weather integration: the previous forecast data is kept, entities stay available with stale data, and the coordinator retries on the next WEATHER_UPDATE_INTERVAL tick.","triggerScenarios":"Scheduled weather refresh where the AEMET Open Data API request fails (HTTP error, rate limit, bad key) or returns data the library cannot parse — all surface as AemetError and are wrapped here. A TimeoutError from the surrounding timeout() is a different, uncaught path.","commonSituations":"AEMET Open Data throttling (their API is aggressively rate-limited per key), API key expiry, temporary outage of the Spanish weather service, or network problems on the HA host.","solutions":["Check the {error} placeholder text in the log for the underlying reason (status code vs parse error).","Verify the API key still works with a direct request to opendata.aemet.es; renew if expired.","If rate-limiting, reduce update frequency via the integration options (increase the update interval) or share the key less.","Wait for the next interval — transient AemetErrors self-heal through coordinator retries.","Persistent parse errors usually mean an AEMET API response change: update the aemet library via a Home Assistant core update."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":"def aemet_coordinator_healthy(coordinator) -> bool:\n    \"\"\"Last weather refresh succeeded (stale data otherwise served).\"\"\"\n    return coordinator.last_update_success","tryCatchPattern":"from homeassistant.exceptions import UpdateFailed\n\ntry:\n    await coordinator.async_refresh()\nexcept UpdateFailed as err:\n    _LOGGER.warning(\"AEMET update failed, keeping previous forecast: %s\", err)","preventionTips":["Increase the update interval in integration options if AEMET rate-limits your key.","Treat weather entities as potentially stale when last_update_success is False.","Update Home Assistant core when AEMET changes API response shapes (library fix follows)."],"tags":["homeassistant","aemet","coordinator","api-error","rate-limit"],"backgroundTag":null,"analyzedSha":"58a3fdb3ea0538617f0a07efcfba6294de64fd59","analyzedAt":"2026-08-14T20:54:38.818Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}