swiftxcodemacostaurientitlements

File Provider extension cannot access App Group container despite identical entitlement


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:

Current Configuration:

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:

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:


Solution

  • 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:

    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.