Fix HACS becomes unresponsive after multiple sidepanel name changes
This PR fixes an issue where HACS becomes completely unresponsive after multiple sidepanel name changes, showing "HACS is not setup" errors and a blank interface.
Problem
When users change the HACS sidepanel name multiple times through the Configuration menu, the integration enters a broken state where:
- The configuration link shows "HACS is not setup"
- The HACS interface becomes blank and unresponsive
- Browser console shows
AttributeError: 'NoneType' object has no attribute 'repositories' - Only a Home Assistant restart restores functionality
Root Cause
The issue occurs during config entry reloads when:
async_unload_entry()is called to reload the configuration- Platform unloading fails (platforms were never properly loaded)
- Despite the failure,
hass.data.pop(DOMAIN, None)still removes the global HACS object - Subsequent websocket calls attempt to access
hacs.repositorieson aNoneobject - This causes continuous
AttributeErrorexceptions that break the frontend
Solution
This PR implements minimal, surgical fixes to handle the race condition:
1. Fixed unload logic (__init__.py)
Only remove the HACS object from hass.data if platform unloading succeeds:
# Only clean up if unload was successful
if unload_ok:
hacs.set_stage(None)
hacs.disable_hacs(HacsDisabledReason.REMOVED)
hass.data.pop(DOMAIN, None)
2. Added null safety to websocket handlers (websocket/repositories.py)
All 5 websocket functions now gracefully handle missing HACS objects:
hacs: HacsBase = hass.data.get(DOMAIN)
if hacs is None:
# Return empty result instead of crashing
connection.send_message(websocket_api.result_message(msg["id"], []))
return
3. Protected platform setup functions (switch.py, update.py)
Prevent KeyError when HACS is not available:
hacs: HacsBase = hass.data.get(DOMAIN)
if hacs is None:
# HACS is not properly initialized
return
Impact
- Before: HACS becomes completely unresponsive after config reload failures
- After: HACS remains functional even when platform unloading fails
- Safety: All websocket calls and platform setups now handle missing HACS gracefully
- User Experience: No more "HACS is not setup" errors or blank interfaces
Testing
The fix has been verified to:
- Handle
NoneHACS objects gracefully in all websocket handlers - Preserve HACS functionality when platform unloading fails
- Prevent KeyError exceptions in platform setup functions
- Maintain normal HACS operation when everything works correctly
Fixes #4436.
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.
Implement the review comment, and extend the tests to cover these scenarios as well.
Added comprehensive test coverage for websocket repository commands when HACS is not initialized. Created tests/websocket/test_repositories_not_initialized.py with parametrized tests for all 5 websocket functions that verify proper error responses instead of crashes or empty results. (091e19c)
The problem is deeper. This resolves only one of the issues. The last one, I think, needs to be done in Home Assistant, and if resolved there, this PR is no longer needed.
The problem is deeper. This resolves only one of the issues. The last one, I think, needs to be done in Home Assistant, and if resolved there, this PR is no longer needed.
Could you clarify what should be fixed in Home Assistant core? Are you referring to the config entry reload mechanism where async_setup_entry is called even when async_unload_entry fails? Should this PR be closed in favor of fixing the root cause in HA core instead of adding these workarounds?
Not yet, I need to investigate more.