Skip to content

[Bug] Desktop 0.5.14 (macOS 26.6, arm64): permanent blank white window — initial tauri://localhost navigation is never decided, resolves as policyAction=Ignore at process teardown #5951

Description

@didme

Summary

On a clean install of Buzz Desktop 0.5.14, the window opens and stays blank white indefinitely (observed >1 hour). The Rust side starts fine and writes its state files; the WebView is created, the custom scheme handlers are registered, and the load of tauri://localhost/index.html is started — but the app's WKNavigationDelegate never calls its decision handler for that navigation. The navigation sits pending forever. When the process is killed, the pending listener finally fires with policyAction=Ignore.

So the app is not crashing or hanging: it silently refuses to load its own frontend.

Environment

Buzz 0.5.14 (CFBundleVersion 0.5.14, CFBundleShortVersionString 0.5.14)
Bundle xyz.block.buzz.app, /Applications/Buzz.app, built 2026-08-15 05:02
OS macOS 26.6 (25G72)
Arch arm64 (Apple silicon)
Install fresh, from the official DMG
Signature Developer ID Application: Block, Inc. (EYF346PHUG), notarization ticket stapled, spctl -a -t exec → accepted, no quarantine xattr

Steps to reproduce

  1. Install Buzz Desktop 0.5.14 from the DMG on macOS 26.6 (arm64).
  2. Launch the app.
  3. Window appears, blank white, and never renders the UI.

Reproduced on 3 consecutive cold launches (PIDs 51572, 51676, 51795). Deleting ~/Library/Application Support/xyz.block.buzz.app and reinstalling does not help — the directory is recreated and the behaviour is identical.

Root cause evidence

1. The navigation is started but never decided

From the unified log, launch at 16:10:27 (PID 51676 / WebContent 51680):

.736  WebPage::registerURLSchemeHandler: Registered handler 2 for the '<private>' scheme
.736  WebPage::registerURLSchemeHandler: Registered handler 3 for the '<private>' scheme
.736  WebPage::registerURLSchemeHandler: Registered handler 1 for the '<private>' scheme
.736  WebPage::registerURLSchemeHandler: Registered handler 10 for the '<private>' scheme
.740  WebPage::loadRequest: navigationID=28, shouldTreatAsContinuingLoad=0, lastNavigationWasAppInitiated=1
.740  FrameLoader::loadWithDocumentLoader: main frame load started
.743  WebPageProxy::decidePolicyForNavigationAction: frameID=4294967297, isMainFrame=1, navigationID=28
.745  beginSafeBrowsingCheck: no threat, completing navigationID=28
      <nothing further for navigationID=28 — no receivedNavigationActionPolicyDecision,
       no didCommitLoad, no didFailProvisionalLoad — for the remaining 25 s of capture>

WebKit only continues a navigation once both the Safe Browsing check has finished and the embedder's navigation delegate has invoked its decision handler. Safe Browsing completed in 2 ms. The delegate never answered.

2. The pending decision resolves as Ignore when the process is torn down

When PID 51676 was killed (16:15:20), the held listener fired at last:

16:15:20.093  WebPageProxy::decidePolicyForNavigationAction: listener called:
              frameID=4294967297, isMainFrame=1, navigationID=28,
              policyAction=Ignore, isAppBoundDomain=0, wasNavigationIntercepted=0
16:15:20.093  WebPageProxy::receivedNavigationActionPolicyDecision:
              frameID=4294967297, isMainFrame=1, navigationID=28, policyAction=Ignore

policyAction=Ignore is the app's own answer — i.e. Buzz's navigation policy path decides to cancel the load of its own index.html, and only surfaces that decision at shutdown. This looks like an on_navigation / capability-scope gate that is waiting on some condition that is never satisfied, and whose fallback is "deny".

3. What the white pixels actually are

.735  DocumentLoader::startLoadingMainResource: Returning empty document
.735  FrameLoader::setState: main frame load completed
.841  RemoteLayerTreeDrawingAreaProxy(24) Unhiding layer tree

The visible window is the initial empty document that precedes navigation 28. Since navigation 28 never commits, that empty document is what the user looks at forever.

4. The main thread is not blocked

sample of buzz-desktop, 5 s, 3765 samples — the main thread is idle in the normal AppKit run loop for 100% of them:

3765 Thread_...  DispatchQueue_1: com.apple.main-thread
  3765 buzz_lib::run
    3765 tauri::app::App<R>::run
      3765 tao::platform_impl::platform::event_loop::EventLoop<T>::run
        3765 -[NSApplication run]
          ... _DPSNextEvent -> mach_msg2_trap

So this is not a deadlock on the main thread — the decision handler is simply never invoked (or is dropped) on a path that later defaults to Ignore.

5. Target URL confirmed

strings on the binary shows tauri://localhost + index.html, and Contents/Resources/ contains only icon.icns — the frontend is embedded and served over the custom scheme, so no network dependency is involved.

Ruled out

  • Crash — zero entries for Buzz in ~/Library/Logs/DiagnosticReports.

  • Gatekeeper / quarantine / signature — see Environment above; all clean.

  • Stale window or app state~/Library/Saved Application State/xyz.block.buzz.app.savedState does not exist; no xyz.block.buzz.app preferences domain (defaults read → "domain does not exist"); .window-state.json is sane (1600×1200 at 0,60, visible: true, maximized: true); wiping Application Support changes nothing.

  • Missing frontend assets — embedded in the binary, and the scheme handlers register successfully.

  • Keychain / SecretStore (initially suspected, then excluded) — an early sample caught a tokio worker in managed_agents::storage::load_managed_agents → SecretStore::load → SecretStore::migrate_legacy_key → migrate_legacy_key_keyring → keyring::Entry::get_password → SecKeychainFindGenericPassword, i.e. the legacy CSSM keychain path. It looked like a plausible blocker, but it is not the cause: samples at t+20 s, t+80 s and t+140 s after launch show no SecretStore frames at all, a single lookup against login.keychain-db (9.3 MB, 2960 generic items) takes 15 ms, and securityd produced only 20 log lines for the process over 3 minutes. The navigation is still un-decided long after that work has finished.

    Worth noting separately though: migrate_legacy_key_keyring goes through SecKeychainFindGenericPassword, the deprecated file-keychain API, which is slow and can prompt; on this machine only one buzz-desktop service entry exists in the login keychain.

Questions for maintainers

  1. Under what conditions does Buzz's navigation policy path return Ignore for tauri://localhost/index.html? Is there an on_navigation handler or a capability/scope check gating the first load on some initialization state?
  2. Is there a path where the decision handler is captured into an async task that can never resolve (leaving the navigation pending until teardown)?
  3. Is there a way to get diagnostics out of a release build without a debug console? The app writes no log file of its own (~/Library/Logs/Buzz does not exist), which made this considerably harder to pin down than it needed to be.

Attachments

  • buzz-report2-sanitized.txt — bundle metadata, code signature, full sample of buzz-desktop, process tree, state directory inventory.
  • buzz-report3-sanitized.txt — keychain measurements, three timed stack samples, and the WebKit navigation trace including the policyAction=Ignore lines.

Paths and local addresses in the attachments have been redacted.

buzz-report2-sanitized.txt
buzz-report3-sanitized.txt

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions