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
- Fresh install (Screen Recording / Accessibility not yet granted).
- Start onboarding, click to grant Screen Recording or Accessibility. Both call
requestPermissionWithFlow (apps/screenpipe-app-tauri/components/onboarding/permissions-step.tsx:107 and :123).
- 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
- 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.
- 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
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, soBundle.modulehits itsfatalErrorwhen 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
e63e248d9.divanshu-go/permission-flow@d7376a1b95acb78700e93505d8ca058e5ddb94ce.Repro
requestPermissionWithFlow(apps/screenpipe-app-tauri/components/onboarding/permissions-step.tsx:107and:123).Crash signature (symbolicated, trimmed)
Root cause
PermissionFlowLocalizer.string(...)loads panel text through SwiftPM'sBundle.module. ThePermissionFlowtarget declaresresources: [.process("Resources")](the.lprojlocalizations), so SwiftPM generatesPermissionFlow_PermissionFlow.bundleat build time. The plugin'sbuild.rslinks the Swift code withswift_rs::SwiftLinker, which links the compiled object code but does not copy that resource bundle into the consuming.app. At runtimeBundle.module's generated accessor searches its candidate paths, finds nothing, and runsfatalError("unable to find bundle named PermissionFlow_PermissionFlow").Evidence
/Applications/screenpipe.app(2.5.28) contains noPermissionFlow*.bundleanywhere (verified withfind).Why the JS fallback does not catch it
requestPermissionWithFlowwrapsstartFlowin try/catch with a fallback (apps/screenpipe-app-tauri/lib/utils/permission-flow.ts), but a native SwiftfatalErrorterminates 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
PermissionFlowLocalizerresilient. Do not touchBundle.moduleunconditionally. Locate the localization bundle with a safe search and fall back to the provided EnglishdefaultValuewhen it is not found, so a missing bundle degrades to English instead of crashing.PermissionFlow_PermissionFlow.bundleis shipped inside the consuming.app(copy*_<Target>.bundleintoContents/Resources/), or load strings fromBundle.mainwhen the package is statically linked.swift_rs::SwiftLinkerdoes not bundle SwiftPM resources, so any target declaringresources:hits this.cc @divanshu-go