integration icon indicating copy to clipboard operation
integration copied to clipboard

Fix HACS becomes unresponsive after multiple sidepanel name changes

Open Copilot opened this issue 5 months ago • 4 comments

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:

  1. The configuration link shows "HACS is not setup"
  2. The HACS interface becomes blank and unresponsive
  3. Browser console shows AttributeError: 'NoneType' object has no attribute 'repositories'
  4. Only a Home Assistant restart restores functionality

Root Cause

The issue occurs during config entry reloads when:

  1. async_unload_entry() is called to reload the configuration
  2. Platform unloading fails (platforms were never properly loaded)
  3. Despite the failure, hass.data.pop(DOMAIN, None) still removes the global HACS object
  4. Subsequent websocket calls attempt to access hacs.repositories on a None object
  5. This causes continuous AttributeError exceptions 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 None HACS 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.

Copilot avatar Jul 06 '25 07:07 Copilot

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)

Copilot avatar Jul 06 '25 09:07 Copilot

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.

ludeeus avatar Jul 08 '25 10:07 ludeeus

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?

Copilot avatar Jul 08 '25 10:07 Copilot

Not yet, I need to investigate more.

ludeeus avatar Jul 08 '25 11:07 ludeeus