I had a (self-induced) hardware failure on an ESP device. I took an identical device, put the same firmware on it I was previously running, HA saw it - but is now warning me about a device conflict.
Seems it doesn't like the MAC address change. In doing some digging, this was a known problem (honestly, it did not occur to me to have to delete the old one before replacing - I guess I am not used to working with low-level stuff. For identical hardware swap, I am used to just writing the configuration and firmware to the replacement, plugging it in, and turning it on - like the last time I replaced a network switch or router).
So there is a 'Migrate configuration to new device'. Great. Except it doesn't work.
Don't ya just love unknof I delete the device, will HA automagically find it and reload the YAML configuration from the device when it adds it, without making changes to the entities or will I have to start over?
f I delete the device, will HA automagically find it and reload the YAML configuration from the device when it adds it, without making changes to the entities or will I have to start over?
wn errors (sorry, that's an annoyance with me - especially if there is a log entry that has the error in it)
From the log:
Logger: aiohttp.server
Source: /usr/local/lib/python3.14/site-packages/aiohttp/web_protocol.py:488
First occurred: 23:16:02 (9 occurrences)
Last logged: 23:35:48
Error handling request from 192.168.2.101
Traceback (most recent call last):
File "/usr/local/lib/python3.14/site-packages/aiohttp/web_protocol.py", line 517, in _handle_request
resp = await request_handler(request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.14/site-packages/aiohttp/web_app.py", line 569, in _handle
return await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.14/site-packages/aiohttp/web_middlewares.py", line 117, in impl
return await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/http/security_filter.py", line 92, in security_filter_middleware
return await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/http/forwarded.py", line 87, in forwarded_middleware
return await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/http/request_context.py", line 26, in request_context_middleware
return await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/http/ban.py", line 90, in ban_middleware
return await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/http/auth.py", line 263, in auth_middleware
return await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/http/headers.py", line 41, in headers_middleware
response = await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/helpers/http.py", line 89, in handle
result = await handler(request, **request.match_info)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/http/decorators.py", line 83, in with_admin
return await func(self, request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/repairs/websocket_api.py", line 159, in post
return await super().post(request, flow_id)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/http/data_validator.py", line 74, in wrapper
return await method(view, request, data, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/helpers/data_entry_flow.py", line 121, in post
result = await self._flow_mgr.async_configure(flow_id, data)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 336, in async_configure
result = await self._async_configure(flow_id, user_input)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 383, in _async_configure
result = await self._async_handle_step(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
flow, cur_step["step_id"], user_input
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 483, in _async_handle_step
result: _FlowResultT = await getattr(flow, method)(user_input)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/esphome/repairs.py", line 65, in async_step_migrate
await async_replace_device(self.hass, entry_id, self.stored_mac, self.mac)
File "/usr/src/homeassistant/homeassistant/components/esphome/manager.py", line 1391, in async_replace_device
dev_reg.async_update_device(
~~~~~~~~~~~~~~~~~~~~~~~~~~~^
device.id,
^^^^^^^^^^
new_connections={(dr.CONNECTION_NETWORK_MAC, new_mac)},
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "/usr/src/homeassistant/homeassistant/helpers/device_registry.py", line 1366, in async_update_device
return self._async_update_device(
~~~~~~~~~~~~~~~~~~~~~~~~~^
device_id,
^^^^^^^^^^
...<23 lines>...
via_device_id=via_device_id,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "/usr/src/homeassistant/homeassistant/helpers/device_registry.py", line 1243, in _async_update_device
added_connections = new_values["connections"] = self._validate_connections(
~~~~~~~~~~~~~~~~~~~~~~~~~~^
device_id, new_connections, False
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "/usr/src/homeassistant/homeassistant/helpers/device_registry.py", line 1413, in _validate_connections
raise DeviceConnectionCollisionError(
normalized_connections, existing_device
)
homeassistant.helpers.device_registry.DeviceConnectionCollisionError: Connections {('mac', '40:f5:20:bd:be:0c')} already registered with DeviceEntry(area_id=None, config_entries={'01KCCX254F6X94T8J9CBBNEFPS'}, config_entries_subentries={'01KCCX254F6X94T8J9CBBNEFPS': {None}}, configuration_url=None, connections={('mac', '40:f5:20:bd:be:0c')}, created_at=datetime.datetime(2026, 5, 24, 3, 10, 25, 847486, tzinfo=datetime.timezone.utc), disabled_by=None, entry_type=None, hw_version=None, id='622fc4e4af4935c9e10c9034e9d1954e', identifiers=set(), labels=set(), manufacturer='Espressif Inc.', model=None, model_id=None, modified_at=datetime.datetime(2026, 5, 24, 3, 10, 25, 847570, tzinfo=datetime.timezone.utc), name_by_user=None, name='', primary_config_entry=None, serial_number=None, _suggested_area=None, sw_version=None, via_device_id=None, _cache={'json_repr': b'{"area_id":null,"configuration_url":null,"config_entries":["01KCCX254F6X94T8J9CBBNEFPS"],"config_entries_subentries":{"01KCCX254F6X94T8J9CBBNEFPS":[null]},"connections":[["mac","40:f5:20:bd:be:0c"]],"created_at":1779592225.847486,"disabled_by":null,"entry_type":null,"hw_version":null,"id":"622fc4e4af4935c9e10c9034e9d1954e","identifiers":[],"labels":[],"manufacturer":"Espressif Inc.","model":null,"model_id":null,"modified_at":1779592225.84757,"name_by_user":null,"name":"","primary_config_entry":null,"serial_number":null,"sw_version":null,"via_device_id":null}', 'as_storage_fragment': <orjson.Fragment object at 0x7f168aad6630>})
So, it looks like there is an issue with the AIO handler.
I am running the latest version, updated as of this morning. (HASSOS).
Any workarounds or known fixes for this issue? I know I can delete the device and let HA find it again, but there is something I am not clear about: If I delete the device, will HA automagically find it and reload the YAML configuration from the device when it adds it, without making changes to the entities or will I have to redo everything that uses the entities? Remember - this is the code I last loaded to the old device this morning. There have been zero changes between then and now, other than the hardware - which is the same hardware, just with a working chip and a different mac address baked into the firmware of the chip.


