Skip to content

fix(desktop): stop macOS attach from aborting on nil NSOpenPanel - #20

Merged
jmfcamp merged 4 commits into
mainfrom
cursor/fix-macos-file-attach-crash-dcfe
Aug 20, 2026
Merged

fix(desktop): stop macOS attach from aborting on nil NSOpenPanel#20
jmfcamp merged 4 commits into
mainfrom
cursor/fix-macos-file-attach-crash-dcfe

Conversation

@jmfcamp

@jmfcamp jmfcamp commented Aug 20, 2026

Copy link
Copy Markdown
Owner

Summary

Attaching a file in the Hula Buzz desktop composer (any <input type="file"> / WKWebView open panel) SIGABRTed on the main thread. The crash is a Rust panic in objc2, not a WebKit bug:

NSOpenPanel::openPanel()objc2::__macro_helpers::retain_semantics::none_failwry::…::run_file_upload_panel → abort.

+[NSOpenPanel openPanel] can return nil. The typed objc2 binding treats that as a hard fail. This shows up on macOS 26 Tahoe and on ad-hoc / unsigned local .app builds (empty codeSigningTeamID): AppKit’s openAndSavePanelService XPC can refuse the request when the on-disk signature does not match the running image, or when the process is not a regular activating UI app (the crash report Role was Background).

This repo pins wry 0.55.1 (via Tauri 2.11.5) and rfd 0.16.0. Upstream tauri-apps/wry#1716 has the nil-guard; it is still open, and crates.io wry 0.56.1 still calls the typed binding. Same panic exists in rfd (tauri-plugin-dialog / pick_and_upload_*).

Fix

  • Vendor wry 0.55.1 and rfd 0.16.0 under desktop/src-tauri/vendor/ and [patch.crates-io] them.
  • Retain the raw +[NSOpenPanel openPanel] / +[NSSavePanel savePanel] return. If nil, cancel the picker (WebKit completion handler / None) instead of aborting.
  • Before creating the panel, set NSApplicationActivationPolicyRegular and activate. Composer attach uses a hidden <input type="file"> (deferUploadsUntilSend), so Wry is the reported stack; rfd covers the native dialog path.
  • Merge-plist: explicit LSUIElement=false and NSPrincipalClass=NSApplication. Hula branding is unchanged (productName Hula Buzz, com.huladesk.buzz, hulabuzz://).

Drop the vendor patches when a crates.io wry/rfd release includes the nil-guard.

Related issue

None found on jmfcamp/buzz (issues disabled). Closest upstream: tauri-apps/tauri#13047, tauri-apps/wry#1716.

Testing

Linux CI: just desktop-tauri-test (includes source-level guards that the vendored files stay nil-safe). This environment cannot run the Mac GUI; do not treat CI as picker reproduction.

Verify on a Mac (the crash host):

  1. Build the desktop app (aarch64-apple-darwin is fine; ad-hoc/local unsigned .app is the reported case).
  2. Open a channel, click attach / file upload in the composer (or any file input).
  3. Expect the native open panel. The process must not abort.
  4. Cancel and choose a file — both should leave the app up. If AppKit still cannot create a panel (signature/XPC), the upload should cancel cleanly with the app still running.

macOS 26.3.1 / Tahoe is the reported OS.

Open in Web Open in Cursor 

cursoragent and others added 4 commits August 20, 2026 20:32
WKWebView file inputs and rfd dialogs call +[NSOpenPanel openPanel].
On macOS 26, especially ad-hoc local builds, that can return nil; the
typed objc2 binding then SIGABRTs. Patch wry 0.55.1 and rfd 0.16.0 to
cancel instead, and keep the app a regular activating UI process.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: jmfcamp <jmfcamp@users.noreply.github.com>
Move Regular activation into tray_menu init so lib.rs stays at the
main-branch line count (file-size ratchet). Provide a no-op stub so
Linux still compiles the tray module.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: jmfcamp <jmfcamp@users.noreply.github.com>
tray_menu is macOS-only, so the vendored wry/rfd nil-panel assertions
never executed in Linux CI. Include the same module from util under
test so the guards stay live.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: jmfcamp <jmfcamp@users.noreply.github.com>
tray_menu is already macOS-only, so the no-op stub was never called
and warned as dead_code when the test module compiled on Linux.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: jmfcamp <jmfcamp@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants