Skip to content

macOS onboarding hard-crash (SIGTRAP): permission-flow Bundle.module fatalError, resource bundle not shipped in .app #3975

@louis030195

Description

@louis030195

TL;DR: The native drag-to-grant permission panel added in #3898 hard-crashes the app (SIGTRAP) the first time it opens during macOS onboarding. The plugin's Swift code is statically linked via swift-rs, but the SwiftPM-generated resource bundle (PermissionFlow_PermissionFlow.bundle) is never copied into the shipped .app, so Bundle.module hits its fatalError when loading the panel's localized strings. It works on the build/CI machine (the bundle sits in the cargo target dir) and crashes for end users.

Affected

Repro

  1. Fresh install (Screen Recording / Accessibility not yet granted).
  2. Start onboarding, click to grant Screen Recording or Accessibility. Both call requestPermissionWithFlow (apps/screenpipe-app-tauri/components/onboarding/permissions-step.tsx:107 and :123).
  3. The native floating drag panel begins to open and the app crashes immediately.

Crash signature (symbolicated, trimmed)

Exception Type: EXC_BREAKPOINT (SIGTRAP)   // Swift fatalError, main thread
0  libswiftCore    _assertionFailure(...)
1  screenpipe-app  closure #1 in variable initialization expression of static NSBundle.module
2  screenpipe-app  one-time initialization function for module
4  libdispatch     _dispatch_once_callout        // first access to Bundle.module
5  screenpipe-app  PermissionFlowLocalizer.string(_:defaultValue:localeIdentifier:)
6  screenpipe-app  PermissionFlowPanelView.headerTitle.getter
...
68 screenpipe-app  FloatingDropPanel.init(controller:)
69 screenpipe-app  PermissionFlowController.showPanel()
70 screenpipe-app  PermissionFlowController.authorize(pane:suggestedAppURLs:sourceFrameInScreen:)
71 screenpipe-app  permission_flow_controller_start_flow

Root cause

PermissionFlowLocalizer.string(...) loads panel text through SwiftPM's Bundle.module. The PermissionFlow target declares resources: [.process("Resources")] (the .lproj localizations), so SwiftPM generates PermissionFlow_PermissionFlow.bundle at build time. The plugin's build.rs links the Swift code with swift_rs::SwiftLinker, which links the compiled object code but does not copy that resource bundle into the consuming .app. At runtime Bundle.module's generated accessor searches its candidate paths, finds nothing, and runs fatalError("unable to find bundle named PermissionFlow_PermissionFlow").

Evidence

  • The shipped /Applications/screenpipe.app (2.5.28) contains no PermissionFlow*.bundle anywhere (verified with find).
  • The only reference to it baked into the main binary is the CI runner's absolute path, which does not exist on user machines:
    /Users/runner/work/screenpipe/screenpipe/apps/screenpipe-app-tauri/src-tauri/target/aarch64-apple-darwin/release/build/permission-flow-<hash>/out/swift-rs/PermissionFlowShimFFI/arm64-apple-macosx/release/PermissionFlow_PermissionFlow.bundle
    
    This is why it renders on the build machine (bundle present in the target dir) and crashes everywhere else.

Why the JS fallback does not catch it

requestPermissionWithFlow wraps startFlow in try/catch with a fallback (apps/screenpipe-app-tauri/lib/utils/permission-flow.ts), but a native Swift fatalError terminates the process before the Tauri command returns, so the promise never rejects and the fallback path is unreachable.

Impact

Activation-blocking. Any new macOS user who has not already granted Screen Recording / Accessibility crashes the moment they try to grant via onboarding. Existing users who granted permissions on a prior version do not re-enter that step, so it is under-reported, but it is a hard crash for fresh installs.

Suggested fixes

  1. Plugin (preferred, permanent): make PermissionFlowLocalizer resilient. Do not touch Bundle.module unconditionally. Locate the localization bundle with a safe search and fall back to the provided English defaultValue when it is not found, so a missing bundle degrades to English instead of crashing.
  2. Packaging: ensure PermissionFlow_PermissionFlow.bundle is shipped inside the consuming .app (copy *_<Target>.bundle into Contents/Resources/), or load strings from Bundle.main when the package is statically linked. swift_rs::SwiftLinker does not bundle SwiftPM resources, so any target declaring resources: hits this.

cc @divanshu-go

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions