{"record":{"id":"9ed57d265dd82afa","repo":"home-assistant/core","slug":"error-9ed57d","errorCode":null,"errorMessage":"{error}","messagePattern":"\\{error\\}","errorType":"exception","errorClass":"UpdateFailed","httpStatus":null,"severity":"error","filePath":"homeassistant/components/airnow/coordinator.py","lineNumber":81,"sourceCode":"            hass,\n            _LOGGER,\n            config_entry=config_entry,\n            name=DOMAIN,\n            update_interval=update_interval,\n        )\n\n    @override\n    async def _async_update_data(self) -> dict[str, Any]:\n        \"\"\"Update data via library.\"\"\"\n        data: dict[str, Any] = {}\n        try:\n            obs = await self.airnow.observations.latLong(\n                self.latitude,\n                self.longitude,\n            )\n\n        except (AirNowError, ClientConnectorError, InvalidJsonError) as error:\n            raise UpdateFailed(error) from error\n\n        if not obs:\n            raise UpdateFailed(\"No data was returned from AirNow\")\n\n        max_aqi = 0\n        max_aqi_level = 0\n        max_aqi_desc = \"\"\n        max_aqi_poll = \"\"\n        for obv in obs:\n            # Convert AQIs to Concentration\n            pollutant = obv[ATTR_API_AQI_PARAM]\n            concentration = aqi_to_concentration(obv[ATTR_API_AQI], pollutant)\n            data[obv[ATTR_API_AQI_PARAM]] = concentration\n\n            # Overall AQI is the max of all pollutant AQIs\n            if obv[ATTR_API_AQI] > max_aqi:\n                max_aqi = obv[ATTR_API_AQI]\n                max_aqi_level = obv[ATTR_API_CATEGORY][ATTR_API_CAT_LEVEL]","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/home-assistant/core/blob/58a3fdb3ea0538617f0a07efcfba6294de64fd59/homeassistant/components/airnow/coordinator.py#L63-L99","documentation":"Raised by the AirNow DataUpdateCoordinator when pyairnow observations.latLong() fails with AirNowError (library/API error, e.g. invalid key or bad request), ClientConnectorError (cannot reach the API host), or InvalidJsonError (malformed response). The raw error string is passed straight into UpdateFailed, so the log/UI shows the library's message verbatim.","triggerScenarios":"Calling the coordinator update with an expired/invalid AirNow API key, coordinates outside the US where AirNow has no data returning an API error, network failure to airnowapi.org, or the API returning non-JSON (proxy/error page).","commonSituations":"AirNow API keys are rate-limited (500/hour) and expire; US-only service used with non-US coordinates; corporate proxy intercepting HTTPS.","solutions":["Read the wrapped error text: 'Invalid API key' means regenerate the key at airnowapi.org and update the entry","Verify the configured latitude/longitude are within the United States","Confirm outbound HTTPS to airnowapi.org works from the HA host","Stay under the 500 requests/hour key limit (check if multiple integrations/scripts share the key)"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Regenerate the AirNow API key when expired and update the entry","Use US coordinates only — AirNow has no data elsewhere","Share the 500 req/hour key budget consciously across integrations"],"tags":["airnow","home-assistant","api-key","network"],"backgroundTag":null,"analyzedSha":"58a3fdb3ea0538617f0a07efcfba6294de64fd59","analyzedAt":"2026-08-14T20:54:38.818Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}