1

I have a Tauri/Rust application with a native Swift File Provider extension. Both are configured to use the same App Group, but the extension cannot access the shared continer at all - it can't even list contents or create files. Getting "Operation not permitted" despite all configurations appearing correct. The Rust side manages the database (used on Windows/Linux/macOS), while the File Provider extension needs read access to display files in Finder.

Architecture:

  • Main app: Tauri/Rust creates SQLite database
  • Extension: Swift File Provider needs read access
  • Communication: App Groups shared container
  • Rust -> Swift via @_cdecl FFI to get container path

Current Configuration:

  • Same Team ID (UF927XXXXX) for both
  • Same App Group (group.com.domain.files)
  • Both sandboxed with identical entitlements
  • File permissions: -rw-rw-rw- (no ACL)
  • Code signing valid
  • Paths identical: /Users/user/Library/Group Containers/group.com.domain.files/files.sqlite

The Problem:

Extension loads but cannot access container - fails on all operations with "Operation not permitted". The extension can't even list the container contents.

What I've Verified:

  • ✅ Entitlements match
  • ✅ Team IDs match
  • ✅ App Groups identical
  • ✅ Sandbox enabled for both
  • ✅ Code signing valid
  • ✅ File exists with correct permissions

Both Entitlements have this content:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
 <key>com.apple.security.app-sandbox</key>
 <true/>
 <key>com.apple.security.application-groups</key>
 <array>
 <string>group.com.domain.files</string>
 </array>
 <key>com.apple.security.files.user-selected.read-write</key>
 <true/>
</dict>
</plist>

Swift Plugin - Get Container Path (called from Rust):

@_cdecl("swift_get_app_group_path")
public func getAppGroupPath() -> UnsafePointer<CChar>? {
 guard let containerURL = FileManager.default.containerURL(
 forSecurityApplicationGroupIdentifier: "group.com.domain.files"
 ) else {
 return nil
 }
 return UnsafePointer(strdup(containerURL.path))
}

Swift Extension - Debug Access (showing failures):

func testContainerAccess() {
 guard let container = FileManager.default.containerURL(
 forSecurityApplicationGroupIdentifier: "group.com.domain.files"
 ) else {
 print("❌ Cannot get container URL")
 return
 }
 
 print("📍 Container path: \(container.path)")
 
 // Test 1: List contents
 do {
 let contents = try FileManager.default.contentsOfDirectory(atPath: container.path)
 print("✅ Can list container: \(contents)")
 } catch {
 print("❌ Cannot list container: \(error)")
 }
 
 // Test 2: Check if DB file exists
 let dbURL = container.appendingPathComponent("files.sqlite")
 if FileManager.default.fileExists(atPath: dbURL.path) {
 print("✅ DB file exists")
 } else {
 print("❌ DB file missing")
 }
 
 // Test 3: Try to read DB file
 do {
 let data = try Data(contentsOf: dbURL)
 print("✅ Can read DB file, size: \(data.count)")
 } catch {
 print("❌ Cannot read DB file: \(error)")
 }
 
 // Test 4: Try SQLite open
 var db: OpaquePointer?
 if sqlite3_open_v2(dbURL.path, &db, SQLITE_OPEN_READONLY, nil) == SQLITE_OK {
 print("✅ SQLite can open database")
 sqlite3_close(db)
 } else {
 let error = String(cString: sqlite3_errmsg(db))
 print("❌ SQLite open failed: \(error)")
 sqlite3_close(db)
 }
}

Swift Extension - Info.plist (File Provider config):

<key>NSExtension</key>
<dict>
 <key>NSExtensionFileProviderDocumentGroup</key>
 <string>group.com.domain.files</string>
 <key>NSExtensionPointIdentifier</key>
 <string>com.apple.fileprovider-nonui</string>
 <key>NSExtensionPrincipalClass</key>
 <string>$(PRODUCT_MODULE_NAME).FileProviderExtension</string>
</dict>

Environment:

  • macOS Tahoe (26.0)
  • Local signing (no Apple Developer account)
  • Xcode
asked Oct 16 at 15:45

1 Answer 1

1

TL;DR

If your extension can't access app groups: Go to extension target → Signing & Capabilities → Remove App Groups capability → Re-add it → Add your app group ID again. Properly configured app groups show checkboxes, broken ones don't.


After weeks of debugging, I discovered the issue was with how Xcode configures app groups for extensions. This was an incredibly frustrating to track down.

I was so stuck that I created an entirely new native macOS app from scratch with the same setup (main app + extension with shared app groups) to isolate whether this was a Rust/Tauri-specific issue. Everything worked fine in the main app, but the exact same error occurred in the extension (the app group was inaccessible).

This proved it wasn't related to my Rust setup at all, but rather something fundamental with Xcode's extension configuration.

I finally noticed something: the app group section looked visually different between the main app and extension:

  • Main app (where I manually added app groups): Shows "checkboxes" next to app group names

  • Extension (where Xcode auto-added app groups during target creation): No checkboxes

See the difference in these screenshots:

Before:Auto added app group

After:Custom added app group

When you create an extension via "New > Target...", Xcode automatically adds the App Groups capability, but it's NOT properly configured despite appearing to be there.

Solution:

  1. In your extension target, go to Signing & Capabilities
  2. Remove the existing App Groups capability
  3. Re-add the App Groups capability using the "+" button
  4. Add your app group identifier again

After doing this, the checkboxes appeared, and everything worked immediately in the native app. I then tried the same fix in my original Rust project, and it worked perfectly.

Xcode adds REGISTER_APP_GROUPS = YES; to the extension target (in project.pbxproj) when properly configured. This flag is missing when the extension is initially created.

It's 2025, and Xcode still has these kinds of silent configuration issues. There's no error message, no warning, just a visual difference (missing checkboxes) that's incredibly easy to miss. The fact that this took weeks to discover when the fix is literally "remove and re-add" is honestly unacceptable from a tooling perspective, specially for new developers.

answered Oct 19 at 11:17
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.