[GH-ISSUE #7598] [Bug]: V26.4.0 Safari tab will become "zombie" if switch to other tabs for 1-2 mins #100537

Closed
opened 2026-05-29 20:33:18 -05:00 by GiteaMirror · 3 comments
Owner

Originally created by @kerhbal on GitHub (Apr 23, 2026).
Original GitHub issue: https://github.com/actualbudget/actual/issues/7598

What happened?

  • In a normal webpage(including Actual budget prior to V26.4.0), if I switch to another tab for a couple mins and come back (Safari, no crazy add-on to put tab to sleep), the tab should still be responsive.
  • After upgrading to V26.4.0, I found that the Actual Budget tab will become "zombie", entire app become unresponsive(edit, the button is still clickable, but no data change happened after clicking), see attached video. (There is a spinning wheel in the middle of screen outside screen recording area)
  • No error in browser console

https://github.com/user-attachments/assets/9af3ec11-a27a-4cd9-91e7-cb1cfebb295d

How can we reproduce the issue?

  1. Open Actual budget in macOS Safari
  2. Switch to another tab for 2mins
  3. Switch back, the app is not responsive any more

Where are you hosting Actual?

Docker

What browsers are you seeing the problem on?

Safari

Operating System

Mac OSX

Originally created by @kerhbal on GitHub (Apr 23, 2026). Original GitHub issue: https://github.com/actualbudget/actual/issues/7598 ### What happened? - In a normal webpage(including Actual budget prior to V26.4.0), if I switch to another tab for a couple mins and come back (Safari, no crazy add-on to put tab to sleep), the tab should still be responsive. - After upgrading to V26.4.0, I found that the Actual Budget tab will become "zombie", entire app become unresponsive(_edit, the button is still clickable, but no data change happened after clicking_), see attached video. (There is a spinning wheel in the middle of screen outside screen recording area) - No error in browser console https://github.com/user-attachments/assets/9af3ec11-a27a-4cd9-91e7-cb1cfebb295d ### How can we reproduce the issue? 1. Open Actual budget in macOS Safari 2. Switch to another tab for 2mins 3. Switch back, the app is not responsive any more ### Where are you hosting Actual? Docker ### What browsers are you seeing the problem on? Safari ### Operating System Mac OSX
GiteaMirror added the bugregression labels 2026-05-29 20:33:23 -05:00
Author
Owner

@matt-fidd commented on GitHub (Apr 28, 2026):

I can't replicate this unfortunately, I do the same as you have described multiple times a day on 26.4 (well, nightly now) and haven't seen the issue. Is there anything else you can provide to help us replicate? Also, can you try with https://app.actualbudget.org to rule out an environment problem

<!-- gh-comment-id:4335082564 --> @matt-fidd commented on GitHub (Apr 28, 2026): I can't replicate this unfortunately, I do the same as you have described multiple times a day on 26.4 (well, `nightly` now) and haven't seen the issue. Is there anything else you can provide to help us replicate? Also, can you try with https://app.actualbudget.org to rule out an environment problem
Author
Owner

@MatissJanis commented on GitHub (Apr 28, 2026):

I think this is related to https://github.com/actualbudget/actual/pull/7172 cc @MikesGlitch

Claude says this:

Root cause: v26.4.0 introduced a SharedWorker-based multi-tab coordinator (PR #7172 — 4f7c3c51a). The coordinator runs a 10-second heartbeat (packages/desktop-client/src/shared-browser-server-core.ts:131-140): every tick it pings every connected port and removes any port that did not pong since the previous tick. Safari aggressively throttles JavaScript in backgrounded tabs (often pausing it entirely after a few seconds), so the heartbeat reply does not come back in time. The coordinator then evicts the port via removePort(); for a single-tab user this also deletes the entire budgetGroups entry (shared-browser-server-core.ts:156-170).

When the user returns to the tab, its WorkerBridge keeps using the now-orphaned MessagePort. Subsequent requests reach the coordinator but portToBudget.get(port) is undefined, so they fall through the routing logic at shared-browser-server-core.ts:692-722 and either are dropped or never reach a leader Worker. Reply handlers in packages/loot-core/src/platform/client/connection/index.ts:9 never resolve, so the UI hangs forever — exactly the "zombie tab + spinner" symptom in the issue.

 A pre-release fix attempt existed for the same family of issues:
 - e477d13fe ("fix safari by detecting crossoriginisolated…") — gated SharedWorker on self.crossOriginIsolated.
 - 8a6b63fc3 ("all ios to fallback to non-shared-worker implemenation") — replaced that with an isIOS UA check inside
 browser-preload.browser.js.

 Both checks were lost when the SharedWorker coordinator PR (4f7c3c51a) was merged into the new file layout — its diff replaces the if (typeof SharedWorker !== 'undefined' && !Platform.isPlaywright && !isIOS) guard with an unconditional if (typeof SharedWorker !== 'undefined' && !Platform.isPlaywright). The later refactor d059a3f50 (renaming browser-preload.browser.js → browser-preload.js) carried this regression forward into v26.4.0.

The bug reporter is on macOS Safari, not iOS, so simply restoring the old isIOS check is not enough — desktop Safari has the same backgrounding/throttling behavior and exhibits the same symptom.
<!-- gh-comment-id:4339332129 --> @MatissJanis commented on GitHub (Apr 28, 2026): I think this is related to https://github.com/actualbudget/actual/pull/7172 cc @MikesGlitch Claude says this: ``` Root cause: v26.4.0 introduced a SharedWorker-based multi-tab coordinator (PR #7172 — 4f7c3c51a). The coordinator runs a 10-second heartbeat (packages/desktop-client/src/shared-browser-server-core.ts:131-140): every tick it pings every connected port and removes any port that did not pong since the previous tick. Safari aggressively throttles JavaScript in backgrounded tabs (often pausing it entirely after a few seconds), so the heartbeat reply does not come back in time. The coordinator then evicts the port via removePort(); for a single-tab user this also deletes the entire budgetGroups entry (shared-browser-server-core.ts:156-170). When the user returns to the tab, its WorkerBridge keeps using the now-orphaned MessagePort. Subsequent requests reach the coordinator but portToBudget.get(port) is undefined, so they fall through the routing logic at shared-browser-server-core.ts:692-722 and either are dropped or never reach a leader Worker. Reply handlers in packages/loot-core/src/platform/client/connection/index.ts:9 never resolve, so the UI hangs forever — exactly the "zombie tab + spinner" symptom in the issue. A pre-release fix attempt existed for the same family of issues: - e477d13fe ("fix safari by detecting crossoriginisolated…") — gated SharedWorker on self.crossOriginIsolated. - 8a6b63fc3 ("all ios to fallback to non-shared-worker implemenation") — replaced that with an isIOS UA check inside browser-preload.browser.js. Both checks were lost when the SharedWorker coordinator PR (4f7c3c51a) was merged into the new file layout — its diff replaces the if (typeof SharedWorker !== 'undefined' && !Platform.isPlaywright && !isIOS) guard with an unconditional if (typeof SharedWorker !== 'undefined' && !Platform.isPlaywright). The later refactor d059a3f50 (renaming browser-preload.browser.js → browser-preload.js) carried this regression forward into v26.4.0. The bug reporter is on macOS Safari, not iOS, so simply restoring the old isIOS check is not enough — desktop Safari has the same backgrounding/throttling behavior and exhibits the same symptom. ```
Author
Owner

@kerhbal commented on GitHub (Apr 29, 2026):

@MatissJanis @matt-fidd sorry this seems to be a false alarm or at least not a persistent issue, the issue is gone after I rebooted my Mac.

<!-- gh-comment-id:4339989863 --> @kerhbal commented on GitHub (Apr 29, 2026): @MatissJanis @matt-fidd sorry this seems to be a false alarm or at least not a persistent issue, the issue is gone after I rebooted my Mac.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/actual#100537