block / block/buzz

[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

Open
#5,951 3 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
32.7k
Forks
4.3k
Avg merge
1d 13h
Merged PRs (30d)
253

Description

# 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 '' scheme
.736 WebPage::registerURLSchemeHandler: Registered handler 3 for the '' scheme
.736 WebPage::registerURLSchemeHandler: Registered handler 1 for the '' scheme
.736 WebPage::registerURLSchemeHandler: Registered handler 10 for the '' 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

```

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::run
3765 tao::platform_impl::platform::event_loop::EventLoop::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](https://github.com/user-attachments/files/31101479/buzz-report2-sanitized.txt)
[buzz-report3-sanitized.txt](https://github.com/user-attachments/files/31101480/buzz-report3-sanitized.txt)

Contributor guide

Open the contributing guide

Research direction

Start by tracing the Tauri macOS navigation delegate for the initial tauri://localhost/index.html load, including the on_navigation and capability/scope paths mentioned in the report. Reproduce the release-build launch while reviewing the attached unified-log traces. Done means the decision handler resolves during startup and the frontend commits instead of leaving the window on the empty document.

Written by the indexing model from the issue text.

Assessment

Tech stack
macos, rust, tauri
Domain
desktop
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.