Skip to main content

Data Update Coordinator now supports Retry After

· 2 min read

Integrations using the Data Update Coordinator can enhance the UpdateFailed exception with a new parameter retry_after to defer the next scheduled refresh by a specified number of seconds and then resume the normal cadence once the API has recovered.

In situations where polling API's would return a sign of being overwhelmed, by throwing an HTTP 429 or providing a Retry-After in the response header, integrations can now honor these backoff signals. The integration and API client must detect these backoff signals and sanitize the API's desired backoff period. The UpdateFailed exception accepts a retry_after parameter (a float in seconds) to delay the next scheduled refresh. Once the API recovers and UpdateFailed is no longer raised, the integration resumes its normal update_interval.

Example of the usage:

try:
request = await self.client.get_information()
except APIClientRateLimited as err:
raise UpdateFailed(
retry_after=60 # This can also be retrieved from the API response itself, or provide a default
) from err

ConfigEntryNotReady

The retry_after parameter is ignored during the Update Coordinator setup phase (async_config_entry_first_refresh). If the first refresh fails, Home Assistant raises a ConfigEntryNotReady exception, allowing config entry setup to retry automatically using the built-in retry. Once the coordinator setup succeeds, retry_after applies to following refreshes.

Improved error handling for oauth2 configuration without internet

· One min read

Integrations using Application Credentials and Configuration via OAuth2 need to update their error handling to correctly handle configuration when the internet is down.

Currently integrations using configuration via OAuth2 call config_entry_oauth2_flow.async_get_config_entry_implementation in async_setup_entry in their __init__.py. Previously when there was no network, this would raise ValueError: Implementation not available, which was a non-retryable error, resulting in the integration needing to be manually reconfigured after internet was restored (see Issues 153956 and 144582). core PR 154579 added config_entry_oauth2_flow.ImplementationUnavailableError and raises it in config_entry_oauth2_flow.async_get_config_entry_implementation when OAuth2 configuration is unavailable because of missing internet. Integrations should catch this error and raise ConfigEntryNotReady. The changed behavior with the new exception will be released in 2025.12.

Here is an example of the migration,

-    implementation = await async_get_config_entry_implementation(hass, entry)
+ try:
+ implementation = await async_get_config_entry_implementation(hass, entry)
+ except ImplementationUnavailableError as err:
+ raise ConfigEntryNotReady(
+ "OAuth2 implementation temporarily unavailable, will retry"
+ ) from err

New integrations will find the correct try / except block generated by python3 -m script.scaffold config_flow_oauth2.

Service translations removed from WebSocket get_services and REST /api/services

· One min read

Action translations defined in strings.json are no longer included in responses from the WebSocket get_services command and the REST /api/services endpoint because they were incomplete and the Home Assistant frontend did not use them.

Legacy, untranslated action names and descriptions from services.yaml remain in both the WebSocket and REST responses.

Fetch complete action translations with the WebSocket command frontend/get_translations.

For details, see core PR 147120.

Changes to the recorder statistics API

· 3 min read

The Python and WS APIs for injecting and modifying statistics have changed.

The following changes have been made to the WS API:

  • The WS command recorder/update_statistics_metadata accepts a unit_class that points to the unit converter used for unit conversions. If there is no compatible unit converter, unit_class should be set to null. Not specifying the unit_class is deprecated and will stop working in Home Assistant Core 2026.11.
  • The metadata object included in the WS command recorder/import_statistics accepts a unit_class that points to the unit converter used for unit conversions. If there is no compatible unit converter, unit_class should be set to null. Not specifying the unit_class is deprecated and will stop working in Home Assistant Core 2026.11.
  • The metadata object included in the WS command recorder/import_statistics accepts a mean_type that specifies the type of mean (0 for no mean, 1 for arithmetic mean, or 2 for circular mean). The mean_type replaces the bool flag has_mean. Not specifying the mean_type is deprecated and will stop working in Home Assistant Core 2026.11.
  • The items in the response to the WS commands recorder/list_statistic_ids and recorder/get_statistics_metadata have mean_type and unit_class.
  • The has_mean in the items in the response to the WS commands recorder/list_statistic_ids and recorder/get_statistics_metadata is deprecated and will be removed in Home Assistant Core 2026.11.

The following changes have been made to the Python API:

  • The function async_update_statistics_metadata accepts a new_unit_class that points to the unit converter used for unit conversions. If there is no compatible unit converter, new_unit_class should be set to None. Not specifying the new_unit_class is deprecated and will stop working in Home Assistant Core 2025.11.
  • The metadata object passed to the functions async_import_statistics and async_add_external_statistics accepts a unit_class that points to the unit converter used for unit conversions. If there is no compatible unit converter, unit_class should be set to None. Not specifying the unit_class is deprecated and will stop working in Home Assistant Core 2025.11.
  • The metadata object passed to the functions async_import_statistics and async_add_external_statistics accepts a mean_type of type StatisticMeanType that specifies the type of mean (NONE, ARITHMETIC, or CIRCULAR). The mean_type replaces the bool flag has_mean. Not specifying the mean_type is deprecated and will stop working in Home Assistant Core 2026.11.
  • The items in the return value of the function async_list_statistic_ids have mean_type and unit_class.
  • The has_mean in the items in the return value of the function async_list_statistic_ids is deprecated and will be removed in Home Assistant Core 2026.11.

Device filter has been removed from target selector

· One min read

The device filter option is no longer supported by the target selector and has been removed from the target selector documentation.

Hassfest has been updated to fail on services with device filter on targets.

Validation of target selectors that specify a device filter will fail in Home Assistant Core 2026.11.

Background

Core helpers that extract entities from targets did not support the device filter. When the user picked a floor, area, label, or category, the filter was ignored. The frontend also ignored the device filter when selecting entities for a target.

A review of all core integrations found no correct use of a device filter on target selectors. We removed the device filter from the target selector rather than implement support for it in Core and the frontend.

Impact on custom integrations and blueprints

Update custom integrations and blueprints to remove device filters from target selectors.

If you have a valid use case for device filters on target selectors, reach out on Discord.

Update coordinator now allows retriggering

· 2 min read

The update coordinator with debouncer active will now accept a request for an update while an update is currently in progress. The request will be queued up to be performed after the current update finishes.

Consider the following case:

async def _update():
a = await get_a()
# A: User or other logic request a new update here through async_schedule_update()
b = await get_b()
return (a,b)

A user or code that request an updates at timestamp A expects that the entities linked will all get new data from that time. However, since we previously ignored that request, entities would have data for the value of a that is from a time before the update request that was ignored.

To make sure we avoid this case, the update coordinator will now schedule an additional update, if a request is received while currently executing an update.

A side effect of this is that it is now possible to schedule an update from inside an update function of the coordinator. That is useful if for example a connection is lost mid update, and we want all entities to indicate directly as unavailable, yet we want to attempt a re-connect as quick as possible but do that in the next update cycle.

Improved API for registering platform entity services

· One min read

Platform entity services should be registered by calling the helper service.async_register_platform_entity_service from the integration's async_setup instead of calling platform.async_register_entity_service during platform set up.

Existing integrations should be migrated to the new API to ensure loading the services does not depend on platform setup.

For examples of migrating, see core PR 152172 and core PR 152047.

Deprecate hass argument in service helpers

· One min read

Summary of changes

Providing hass argument to the following service helpers is deprecated: verify_domain_control, extract_entity_ids, async_extract_entities, async_extract_entity_ids, and async_extract_config_entry_ids.

Since release 2025.1 (via core PR #133062), a reference to HomeAssistant is available as a property of the ServiceCall object, and it became redundant to pass the hass object to the above helpers.

To update your integration, just remove the hass argument.

Support for the hass argument will be removed in Home Assistant 2026.10.

Examples

ID extraction helpers

# Old
# target_entry_ids = await async_extract_config_entry_ids(hass, service_call)
# entity_ids = await async_extract_entity_ids(hass, service_call)
# entities = await service.async_extract_entities(hass, platform_entities.values(), service_call)

# New
target_entry_ids = await async_extract_config_entry_ids(service_call)
entity_ids = await async_extract_entity_ids(service_call)
entities = await service.async_extract_entities(platform_entities.values(), service_call)

Decorator helper

# Old
# @verify_domain_control(hass, DOMAIN)
# async def do_action(call: ServiceCall) -> None:
# ...

# New
@verify_domain_control(DOMAIN)
async def do_action(call: ServiceCall) -> None:
...