Custom panel element removed from ha-panel-custom after Chrome background tab throttling

I’m wondering if anyone has experiemce with custom panel lifecycles, specifically disappearing due to inactive tab browser throttling.

Background: I’m building a custom integration called Object Registry — an in-memory named JSON object store that lets automations and scripts look up reusable mapping data at runtime via service calls. A concrete use case: mapping ISY/Eisy remote button events to Hue light actions without hardcoding relationships across dozens of automations. The panel provides full CRUD management with live concurrent-edit detection, real-time list updates via WebSocket, validation, and rename warnings. I initially explored a subentry/config flow approach but couldn’t find a clean solution for inline JSON editing in that flow, which drove the decision to build a custom sidebar panel instead.

:package: Repository: ferventgeek/ha-object-registry

Context: The integration uses panel_custom with embed_iframe=False and a vanilla HTMLElement . Everything works great when the tab is active. But, after ~5 minutes in a background tab, Chrome throttles JS execution and the panel goes blank.

What I’ve diagnosed:

Through DOM inspection and console logging I’ve confirmed:

  1. After background throttling, <ha-panel-custom> becomes completely empty — <object-registry-panel> is removed from the DOM entirely
  2. While the tab is active, set hass fires continuously (HA state heartbeat) — confirmed via logging
  3. After throttling, set hass stops firing (Chrome suspended execution)
  4. On tab return, set hass resumes but the element is already gone — nothing to receive it
  5. visibilitychange + pushState/popstate navigation workaround fires but doesn’t trigger partial-panel-resolver to remount the element
  6. Clicking any other sidebar item and returning immediately fixes it — partial-panel-resolver remounts cleanly

Question: Is there a supported lifecycle hook or event we should listen to that signals partial-panel-resolver is remounting a panel? Or is there a way to prevent ha-panel-custom from being emptied during background throttling?

I’d considered trying to hook into the visibility status change on the DOM, then trying to force a refresh. That would lose any edits in the editor by reloading the list view, but feels hacky and brittle to maintain:

if (!window._objectRegistryVisibilityHandler) {
  window._objectRegistryVisibilityHandler = () => {
    if (document.visibilityState !== "visible") return;
    if (window.location.pathname !== "/object_registry") return; // only our panel
    const current = window.location.pathname;
    window.history.pushState(null, "", "/");
    window.history.pushState(null, "", current);
    window.dispatchEvent(new PopStateEvent("popstate"));
  };
  document.addEventListener("visibilitychange", window._objectRegistryVisibilityHandler);
}

HA version: 2026.4 Panel registration: panel_custom.async_register_panel with embed_iframe=False

Thanks again for any suggestions!

1 Like