Skip to main content

Updated guidelines for helper integrations linking to other integration's device

· 2 min read

Helper integrations should not add their own config entries to the source entity's device or to a user selected device. Instead, they should just link their entities to the device of the source entity.

Adding the helper config entry to another integration's device is no longer supported and will stop working in Home Assistant Core 2026.8.

Background

The architecture proposal home-assistant/architecture#1226 makes device connections and identifiers unique per integration domain instead of globally unique. This is not an issue for most integrations, but helper integrations with config flows are an exception.

Suggested change

In the helper entity's constructor, set self.device_entry to the source device

class HelperEntity(Entity)

def __init__(hass: HomeAssistant, source_entity_id: str, ...) -> None:
self.device_entry = async_entity_id_to_device(
hass,
source_entity_id,
)

Do not add the helper config entry to the source device directly

Do not add the config entry to the source device directly, meaning that this pattern is no longer allowed

device_registry.async_update_device(
source_device.id,
add_config_entry_id=helper_config_entry.entry_id,
)

Do not add the helper config entry to the source device implicitly

Don’t set self._attr_device_info and don’t override device_info to return identifiers and connections for a device from another integration as that will mean the helper config entry is added to the source device. Instead, Set self.device_entry in the helper entity to link the helper entity to another integration's device as in the example above.

Cleaning up the device registry

A helper function, homeassistant.helpers.helper_integration.async_remove_helper_config_entry_from_source_device is available to aid the clean up. Core integrations have been modified to call this helper from a config entry migration step.

Handling removed devices

It is up to the helper integration to decide how to handle a removed device; most core helpers set self.device_entry to None. Note that DeviceRegistry.async_get returns None if passed a device_id which doesn't exist.

Sample implementations

The derivative core integration, which previously added its config entry to the source entity's device, has been updated to just link the helper entity to the source entity's device in core PR #148674.

The template core integration, which previously added its config entry to a user selected device, has been updated to just link the helper entity to the user selected device in core PR #148756.

Handling open file limit in add-ons since OS 16

· 2 min read

With the release of Home Assistant OS 16, the default limit for open file descriptors in Docker containers (and, by extension, all add-ons and the processes within them) has changed. Home Assistant OS now uses the default values provided by Systemd: a soft limit of 1024 and a hard limit of 524288 open files.

This is a change from previous OS versions, where the limit was set to "infinity" (effectively a value over 1 billion) — also introduced as an upstream change — since Home Assistant OS 10. The new limits are consistent with common practices on modern Linux systems and follow changes gradually being adopted across other Linux distributions.

For more details on these limits and best practices, see Lennart Poettering's explanation on File Descriptor Limits. In summary, applications that require more than the default soft limit of 1024 file descriptors should explicitly raise their own limit at startup, up to the hard limit imposed by the system (in our case, 524288). This approach ensures each application only requests the resources it needs and avoids system-wide high limits that may lead to unexpected resource exhaustion.

What does this mean for add-on developers?

  • If your application running as an add-on needs to open more than 1024 files (sockets, pipes, etc.), you should adjust the limit yourself, for example using ulimit -Sn <value>, as long as <value> does not exceed the hard limit (which can be checked with ulimit -Hn).
  • Most add-ons will likely not be affected by this change, but some — such as those handling many network connections or accessing numerous files (e.g., databases or file sharing applications) — may need to adapt their startup routines.

What happens if the limit is too low?

If an add-on or its application requires more file descriptors than the default soft limit (1024) and does not raise the limit itself, it may fail to open additional files, sockets, or network connections once the limit is reached. This typically results in errors such as "Too many open files" or "No file descriptors available" (EMFILE), failing network connections, or malfunctioning services.

If you have any questions or encounter issues, please refer to this GitHub discussion, which also contains more details and background information about this topic.

Vacuum battery properties are deprecated

· One min read

As of Home Assistant Core 2025.8, the two properties for battery in StateVacuumEntity, battery_level and battery_icon, have been deprecated.

The battery_level and battery_icon properties should be replaced by a separate sensor with the battery sensor device class and optionally a customized icon if the default icon of the battery sensor device class isn't wanted. Optionally consider to also provide a binary sensor with the charging device class if it's currently charging or not.

There is a one-year deprecation period, and the two battery properties will stop working from 2026.8 to ensure all custom integration authors have time to adjust.

More details can be found in the architectural decision.

Sensor device classes now have default display precision

· One min read

If a numeric sensor doesn't have a suggested display precision set by its integration, Home Assistant will now use a default display precision based on the sensor's device class.

New device classes should be added to UNITS_PRECISION in homeassistant/components/sensor/const.py, along with the proper unit and the desired default display precision. See the docstring of that constant for more details on how to choose the right unit and precision.

The rounding that was previously applied to the sensor state when a unit conversion was happening is now removed, and the sensor state contains the full raw value.

It is still recommended that integrations set the suggested_display_precision on their sensors. This change is a fallback mechanism to ensure a consistent experience across all numeric sensors.

For more details check the implementation pull request and the Sensor entity documentation.

Icon translations now support ranges

· One min read

Icon translations now support defining icons based on numeric ranges. This means integration authors can define icons that change based on numeric values without implementing custom logic in their code.

Previously, icon translations only supported state-based icons, where specific states would map to specific icons. While this works well for discrete states like "on"/"off", it required custom code to handle numeric values like battery levels or signal strength indicators.

Range-based icons are defined in the icons.json file:

{
"entity": {
"sensor": {
"battery_level": {
"default": "mdi:battery",
"range": {
"0": "mdi:battery-outline",
"10": "mdi:battery-10",
"20": "mdi:battery-20",
"30": "mdi:battery-30",
"40": "mdi:battery-40",
"50": "mdi:battery-50",
"60": "mdi:battery-60",
"70": "mdi:battery-70",
"80": "mdi:battery-80",
"90": "mdi:battery-90",
"100": "mdi:battery"
}
}
}
}
}

The system selects the icon associated with the highest range value that's less than or equal to the entity's current value. For example:

  • A value of 15 will show the mdi:battery-10 icon
  • A value of 45 will show the mdi:battery-40 icon
  • A value of 100 will show the mdi:battery icon

For implementation details, see the icon translations documentation.

Device tracker TrackerEntity location accuracy attribute type change

· One min read

The type of location_accuracy attribute (short hand _attr_location_accuracy) of the TrackerEntity class of the device_tracker entity component has been changed from int to float.

Type conversions in case the source value is a float are no longer needed.

Example

class ExampleTrackerEntity(TrackerEntity):
"""Test tracker entity."""

_attr_location_accuracy: float = 2.5

@cached_property
def location_accuracy(self) -> float:
"""Return the location accuracy of the device.

Value in meters.
"""
return self._attr_location_accuracy

Searching in media players

· One min read

Media players can now allow users to search through the media, by adding MediaEntityFeature.SEARCH_MEDIA and implementing async_search_media. The users can filter the search result by a search query and a list of MediaClasses that the returned results should have. For more info, see the updated documentation.

UnitSystem dataclass is now frozen

· One min read

UnitSystem class is changed to a frozen data class, and all instances derived from it are now frozen.

The following unit systems that derived from the UnitSystem class are now frozen:

  • METRIC_SYSTEM
  • US_CUSTOMARY_SYSTEM

The reason for this change is that Unit systems are constants that should not be modified. An integration that modifies these constants can break unit conversions and create undesired output for other components of Home Assistant.

With a frozen data class an attempt to modify the UnitSystem constant will fail:

dataclasses.FrozenInstanceError: cannot assign to field 'temperature_unit'

This change was introduced in the home assistant core PR #140954.

Changes to ConfigSubentryFlow

· One min read

ConfigSubentryFlow._reconfigure_entry_id has been renamed to ConfigSubentryFlow._entry_id and ConfigSubentryFlow._get_reconfigure_entry has been renamed to ConfigSubentryFlow._get_entry.

The reason for the change is that both sub entry user flows and subentry reconfigure flows need access to parent config entry, e.g. getting options, data, etc.

Custom integrations which call either of the renamed methods need to update their implementations.

The change is introduced in the home assistant core PR #141017.