ZHA OTA firmware updates are one of those features that work fine right up until they don’t, and once they don’t, the documentation sends you somewhere that tells you it’s out of date. I went through the official ZHA integration page, both of the zigpy wiki’s OTA pages, and the two most active Home Assistant community threads on the topic to work out why some Zigbee devices get automatic firmware updates and others sit at “unknown” forever.
The short version: ZHA has OTA enabled by default, but only five manufacturers are switched on out of the box. Getting anyone else’s firmware into the update flow means editing configuration.yaml with a syntax that’s changed at least once in the past two years, and as of January 2026 there’s a second system, an official central firmware repository, running alongside the older provider-based approach. The pieces are documented — they’re just not documented where the official integration page points you. (This article is about end-device OTA. Updating your coordinator’s own radio firmware is a separate job with separate failure modes, and isn’t covered here.)
What ZHA turns on by default
ZHA’s OTA feature rides on Home Assistant’s standard Update entities. An entity only does anything useful if two conditions hold: the device itself supports OTA, and the manufacturer publishes firmware images somewhere ZHA can reach.
Out of the box, that second condition is only satisfied for five manufacturers: IKEA, Inovelli, Ledvance/OSRAM, Sonoff/iTead, and Third Reality. Everyone else’s OTA support exists in ZHA but ships turned off. The reasoning on the official integration page, paraphrased, comes down to risk: updates from other manufacturers may change or remove device functionality, may require reconfiguring the device afterward, or come from community-contributed providers that haven’t been tested as thoroughly.
ZHA’s default-five list has stayed the same for a while, but nothing in the docs guarantees it won’t change. Check the current integration page before assuming your manufacturer is or isn’t included.
If your device’s brand isn’t on that list, the entity showing “unknown” doesn’t mean anything is broken. It means the provider for that manufacturer was never turned on.
Why the docs seem to dead-end (and where they actually go)
Here’s the trap that sends most people to a forum thread. The ZHA integration page doesn’t explain how to add providers — it points to “the zigpy documentation for OTA configuration.” Follow that link and you land on the zigpy wiki’s OTA Device Firmware Updates page, which opens with a banner saying its content is no longer up to date for Home Assistant Core 2024.2.0 and later. Reasonable conclusion: this isn’t documented anywhere current.
It is. The zigpy wiki has a second, separate page — OTA Configuration — that documents the current config block, provider types and all. The official integration page links the stale sibling. That’s the whole gap: not missing documentation, a bad link.
The stale page is still useful for recognising old config when you see it. Its documented syntax used individual boolean keys nested under zha.zigpy_config.ota: ikea_provider, inovelli_provider, ledvance_provider, salus_provider, sonoff_provider, and thirdreality_provider, plus a separate otau_directory key for a local firmware folder. A 2024 community thread documents these keys being deprecated. If a snippet you found online uses any of those _provider: true keys, stop copying it.
Current syntax: extra_providers
The replacement is a single extra_providers list, where each entry is a typed dictionary rather than a boolean flag. A basic example for turning on providers beyond the default five looks like this:
zha:
zigpy_config:
ota:
extra_providers:
- type: ikea
- type: thirdreality
otau_directory and custom_quirks_path are still valid as separate keys under the same ota: block. They weren’t folded into extra_providers.
Beyond the plain manufacturer-name entries, the OTA Configuration page documents several other provider types:
| Type value | What it does |
|---|---|
Manufacturer name (e.g. ikea, thirdreality, sonoff, salus) |
Turns on that manufacturer’s own OTA source |
ZHA’s central repository, with a channel option |
Opts into the official zigpy-ota index, with beta or dev for pre-release firmware |
z2m |
Points ZHA at Zigbee2MQTT’s long-running firmware index (the Koenkk/zigbee-OTA repository). Off by default and community-contributed |
z2m_local |
Same index, but a local clone you’ve cloned yourself, keyed on an index_file |
zigpy_remote |
An arbitrary URL pointing at an OTA index file |
advanced |
Loads firmware images from a local folder you manage yourself, via a path value |
One caveat: zigpy reworked this configuration format in version 0.65.0, and the type name for the central repository is spelled zigpy in some sources and zigpy_ota in others. Rather than trust one spelling — including ours — check it against the OTA Configuration page for the zigpy version your install is actually running. The channel option exists because the zigpy-ota repository organises its index files by channel (stable, beta, dev) on its release branch, so you’re picking which index ZHA reads, not a per-device setting.
The z2m type is the interesting one for anyone who’s spent time in Zigbee2MQTT’s ecosystem. ZHA can check the same centralized firmware index Z2M has relied on for years, rather than waiting on each manufacturer to plug into ZHA’s own systems separately. If you’re still deciding between the two stacks, the broader ZHA-versus-Zigbee2MQTT trade-offs go well beyond firmware.
What changed in HA 2026.1.0: a central firmware repository
Home Assistant Core 2026.1.0, released January 7, 2026, added something the ZHA integration page still doesn’t mention as of this writing: an official central zigpy-ota firmware image repository, built on the same idea Zigbee2MQTT proved out with its own index. Manufacturers submit an issue with a firmware image URL, a PR gets auto-created, and the repository tracks stable and beta channels along with manufacturer feedback.
I think this is the right move, and overdue. Z2M’s centralized index has been one of its quiet advantages over ZHA for years: updates don’t depend on each vendor building its own ZHA-specific integration. Having ZHA converge on the same model closes a real gap, once it’s fully built out.
That “once” is doing real work. The announcement thread describes what shipped in 2026.1.0 as an early version, this wasn’t called out prominently in the release notes, and onboarding is opt-in per manufacturer rather than automatic.
The January 2026 announcement thread named Aeotec and Innr as manufacturers the ZHA developers were actively working with, and Sonoff has since started submitting new firmware to zigpy-ota. That’s a handful of vendors, not the whole Zigbee catalogue. Manufacturers not yet onboarded still depend on the older extra_providers path or a local folder, not the new repo.
No provider for your manufacturer yet? The local folder fallback
If your device’s manufacturer isn’t in the default five, hasn’t published a provider anyone’s documented, and hasn’t been onboarded to the central repository, you’re not out of options — just out of automation. The otau_directory key, or the advanced provider type with its path value depending on which mechanism you’re using, lets you point ZHA at a folder of firmware files you’ve placed there yourself, usually downloaded manually from the manufacturer’s own site or support channel.
It’s manual and it doesn’t self-update, but it’s the one path that doesn’t depend on anyone building infrastructure for your specific manufacturer first. Worth separating from a different problem it’s easy to confuse this with: if ZHA doesn’t recognise the device properly at all, exposing wrong or missing entities, that’s a quirk gap rather than a firmware-provider gap, and no amount of OTA config will fix it.
Known rough edges: “update: unknown” even after following a guide
If you’ve already added an extra_providers entry copied from a forum post and your Update entity still says “unknown,” you’re not necessarily doing anything wrong. The most-referenced 2026 community guide on this topic was started in January and was still collecting replies through June. Several of those replies are from users whose devices sat at “unknown” after following the guide’s own steps — the reports accumulated in the thread rather than being resolved in it, which is what makes them evidence about the state of the feature rather than about one person’s config.
Adding an extra_providers entry doesn’t guarantee an Update entity populates. Restart Home Assistant fully after any change to this config block, check the provider’s type value against the current OTA Configuration wiki page rather than an old forum post, and confirm your specific device actually has firmware published by that provider before assuming the config is broken.
This is a genuinely rough corner of ZHA in 2026, not a solved problem with one canonical fix. Between the deprecated syntax still circulating online, the central repository being early, and the official docs pointing at a stale wiki page, it’s easy to end up with a config that looks right and still doesn’t work. Zigbee2MQTT’s OTA flow has its own share of stuck-update reports, for what it’s worth — this isn’t a ZHA-specific curse.
Frequently asked questions
Does ZHA support OTA firmware updates?
Yes. It’s enabled by default and uses standard Home Assistant Update entities, but only five manufacturers (IKEA, Inovelli, Ledvance/OSRAM, Sonoff/iTead, Third Reality) have their providers turned on out of the box.
Why isn’t my Zigbee device showing a firmware update in ZHA?
Most commonly, because the device’s manufacturer isn’t one of the five default providers. It can also mean the manufacturer hasn’t published firmware images at all, or that your extra_providers config isn’t using the type value ZHA expects.
What is extra_providers in ZHA’s configuration?
It’s the current YAML syntax, under zha.zigpy_config.ota, for turning on OTA providers beyond the default five. It replaced an older set of individual boolean keys (ikea_provider, sonoff_provider, and similar) that are now deprecated.
How do I point ZHA at Zigbee2MQTT’s firmware repository?
An extra_providers entry with type: z2m makes ZHA check Zigbee2MQTT’s firmware index, the Koenkk/zigbee-OTA repository. It’s off by default and community-contributed. A z2m_local variant reads a local clone of that index instead, via an index_file value.
What changed with ZHA’s new central firmware repository in 2026?
Home Assistant Core 2026.1.0 added an official zigpy-ota repository modeled on Zigbee2MQTT’s long-standing firmware index. It’s opt-in per manufacturer and was described as an early version at launch, so it doesn’t yet cover every device that lacks a default provider.
What’s solid, and what still depends on the vendor
The load-bearing facts here come from official sources: the default-enabled five and the reasoning behind that choice from the ZHA integration page, the deprecated boolean keys, the current extra_providers structure and its types from the zigpy wiki’s OTA Configuration page, and the January 2026 central repository as a real, shipped feature. The one thing to double-check yourself is the exact type name for the central-repository provider, since zigpy changed this format in 0.65.0 and both spellings still circulate.
None of this changes what stays local. Whichever provider path you use, OTA firmware for a Zigbee device flows through your own coordinator, not a manufacturer’s cloud API — the provider config only decides where the image file is fetched from before it’s pushed over Zigbee. What depends on the vendor is upstream of that: whether they publish firmware images publicly at all, and whether they’ve onboarded to either the provider system or the central repository.
Whether the central repository ends up replacing extra_providers entirely, or just sits alongside it for the manufacturers who opt in, isn’t settled as of this writing. If OTA gaps are what brought you here, it’s worth rereading the ZHA release notes each time Home Assistant Core ships — ZHA’s behaviour has shifted under a point release before, and this is clearly still being built out under the hood.