Error: _SwiftData_SwiftUI: one-time initialization function for empty

My App keeps crashing in the background and I don't know why. I'm using SwiftData and SwiftUI. I'm setting up a .backgroundTask like this:

import SwiftUI
import SwiftData
import TipKit

@main
struct MyAppName: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

    @State var navManager = NavigationManager.load()
    @State var alerter: Alerter = Alerter()

    var sharedModelContainer: ModelContainer = {
        do {
            return try ModelContainer(for: DataController.schema, configurations: [DataController.modelConfig])
        } catch {
            fatalError("Could not create ModelContainer: \(error)")
        }
    }()

    var body: some Scene {
        WindowGroup {
            SetupView()
                .accentColor(.myAccentColor)
                .environment(alerter)
                .alert(isPresented: $alerter.isShowingAlert) {
                    alerter.alert ?? Alert(title: Text(verbatim: ""))
                }
                .task {
                    try? Tips.configure([
                        .displayFrequency(.immediate),
                        .datastoreLocation(.applicationDefault)
                    ])
                }
                .onAppear {
                    setUpAppDelegate()
                }
        }
        .modelContainer(sharedModelContainer)
        .backgroundTask(.appRefresh(Const.backgroundAppRefreshId)) { @MainActor in
            let container = sharedModelContainer
            await RefreshManager.handleBackgroundVideoRefresh(container)
        }
        .environment(navManager)
    }

    func setUpAppDelegate() {
        appDelegate.navManager = navManager
    }
}

The RefreshManager.handleBackgroundRefresh(...) goes on to load data and then insert models for them via SwiftData. It only happens occasionally and afaik only in the background. Weirdly enough the issue seems to be there even when I only print something in the background task. Even when I don't schedule/set a background task at all. How can that be? The crashes started in the version that included the .backgroundTask, although perhaps it's related to something else. I'm still trying to further narrow it down.

This is the crash report that I'm getting:

Exception Type:  EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x00000001a1bb98c0
Termination Reason: SIGNAL 5 Trace/BPT trap: 5
Terminating Process: exc handler [809]

Triggered by Thread:  0


Thread 0 name:
Thread 0 Crashed:
0   libswiftCore.dylib            	0x00000001a1bb98c0 _assertionFailure(_:_:file:line:flags:) + 264 (AssertCommon.swift:144)
1   libswiftCore.dylib            	0x00000001a1c27d14 swift_unexpectedError + 664 (ErrorType.swift:188)
2   _SwiftData_SwiftUI            	0x000000024310cd78 one-time initialization function for empty + 300 (ModelContainer+Extensions.swift:5)
3   libdispatch.dylib             	0x00000001ab16add4 _dispatch_client_callout + 20 (object.m:576)
4   libdispatch.dylib             	0x00000001ab16c654 _dispatch_once_callout + 32 (once.c:52)
5   _SwiftData_SwiftUI            	0x000000024310cdf8 one-time initialization function for empty + 124 (ModelContainer+Extensions.swift:12)
6   libdispatch.dylib             	0x00000001ab16add4 _dispatch_client_callout + 20 (object.m:576)
7   libdispatch.dylib             	0x00000001ab16c654 _dispatch_once_callout + 32 (once.c:52)
8   _SwiftData_SwiftUI            	0x0000000243122170 key path getter for EnvironmentValues.modelContext : EnvironmentValues + 140 (<compiler-generated>:0)
9   libswiftCore.dylib            	0x00000001a1ce4628 RawKeyPathComponent._projectReadOnly<A, B, C>(_:to:endingWith:) + 1012 (KeyPath.swift:1701)
10  libswiftCore.dylib            	0x00000001a1ce3ddc KeyPath._projectReadOnly(from:) + 1036 (KeyPath.swift:331)
11  libswiftCore.dylib            	0x00000001a1ce8348 swift_getAtKeyPath + 24 (KeyPath.swift:2029)
12  SwiftUI                       	0x00000001a7af4814 EnvironmentBox.update(property:phase:) + 872 (Environment.swift:273)
13  SwiftUI                       	0x00000001a782a074 static BoxVTable.update(ptr:property:phase:) + 396 (DynamicPropertyBuffer.swift:294)
14  SwiftUI                       	0x00000001a78297b0 _DynamicPropertyBuffer.update(container:phase:) + 104 (DynamicPropertyBuffer.swift:215)
15  SwiftUI                       	0x00000001a887fb78 closure #1 in closure #1 in DynamicBody.updateValue() + 104 (DynamicProperty.swift:447)
16  SwiftUI                       	0x00000001a887fbb8 partial apply for closure #1 in closure #1 in DynamicBody.updateValue() + 28 (<compiler-generated>:0)
17  libswiftCore.dylib            	0x00000001a1bcc068 withUnsafeMutablePointer<A, B>(to:_:) + 28 (LifetimeManager.swift:82)
18  SwiftUI                       	0x00000001a887f9dc closure #1 in DynamicBody.updateValue() + 408 (DynamicProperty.swift:446)
19  SwiftUI                       	0x00000001a887f5c0 DynamicBody.updateValue() + 712 (DynamicProperty.swift:445)
20  SwiftUI                       	0x00000001a71e8bf8 partial apply for implicit closure #1 in closure #1 in closure #1 in Attribute.init<A>(_:) + 32 (<compiler-generated>:0)
21  AttributeGraph                	0x00000001cbd4c240 AG::Graph::UpdateStack::update() + 512 (ag-graph-update.cc:578)
22  AttributeGraph                	0x00000001cbd42f38 AG::Graph::update_attribute(AG::data::ptr<AG::Node>, unsigned int) + 424 (ag-graph-update.cc:719)
23  AttributeGraph                	0x00000001cbd42810 AG::Graph::input_value_ref_slow(AG::data::ptr<AG::Node>, AG::AttributeID, unsigned int, unsigned int, AGSwiftMetadata const*, unsigned char&, long) + 720 (ag-graph.cc:1429)
24  AttributeGraph                	0x00000001cbd423a4 AGGraphGetValue + 228 (AGGraph.mm:701)
25  SwiftUI                       	0x00000001a887f548 DynamicBody.updateValue() + 592 (DynamicProperty.swift:444)
26  SwiftUI                       	0x00000001a71e8bf8 partial apply for implicit closure #1 in closure #1 in closure #1 in Attribute.init<A>(_:) + 32 (<compiler-generated>:0)
27  AttributeGraph                	0x00000001cbd4c240 AG::Graph::UpdateStack::update() + 512 (ag-graph-update.cc:578)
28  AttributeGraph                	0x00000001cbd42f38 AG::Graph::update_attribute(AG::data::ptr<AG::Node>, unsigned int) + 424 (ag-graph-update.cc:719)
[...]
107 SwiftUI                       	0x00000001a7cf79fc static App.main() + 132 (App.swift:114)
108 MyAppName                     	0x0000000100e6d120 static MyAppNameApp.$main() + 52 (MyAppNameApp.swift:0)
109 MyAppName                     	0x0000000100e6d120 main + 64
110 dyld                          	0x00000001c67c2d84 start + 2240 (dyldMain.cpp:1298)

The report also says key path getter for EnvironmentValues.modelContext, which seems odd. Any idea where I could start to look for the issue? I'm currently just trying things out, pushing them to TestFlight and waiting for crashes to happen. As soon as I can narrow it down further I'll update this.

Answered by fer0n in 784722022

I think I finally figgured it out!

This Thread discusses a similar issue, it seems to be a SwiftUI bug. When the App launches in the background from being inactive, it’s crashing when an @Environment variable is used in the root ContentView (only seems to happen for .modelContext for me).

I was able to reliably reproduce it by launching the App in the background directly.

This is what I was doing:

@main
struct MyApp: App {
    var sharedModelContainer: ModelContainer = {
        // ...
    }()
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .modelContainer(sharedModelContainer)
    }
}

struct ContentView: View {
    @Environment(\.modelContext) var modelContext

    var body: some View {
        MyView()
    }
    
    func someFunc() {
        modelContext.insert(...)
    }
}

I’m now passing the container to the root view as an argument and adding it there via .modelContainer(...), which seems to have fixed the issue:

@main
struct MyApp: App {
    var sharedModelContainer: ModelContainer = {
        // ...
    }()
    
    var body: some Scene {
        WindowGroup {
            ContentView(container: sharedModelContainer)
        }
    }
}

struct ContentView: View {
    let container: ModelContainer
    
    var body: some View {
        MyView()
            .modelContainer(container)
    }
    
    func someFunc() {
        let modelContext = ModelContext(container)
        modelContext.insert(...)
    }
}

Please post a full crash report, per the instructions in Posting a Crash Report.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Here's the full crashlog:

. Is this sufficient or should I also add a .xccrashpoint file?

Turning off both Background Fetch and Remote notifications gets rid of the issue, so that part seems to make more sense. I want to use both, though. It doesn't feel like it has something to do with the way I set up the .backgroundTask, as it's also happening when I don't do use it at all.

What parts of the Application are run when it refreshes in the background? Why does GeometryReader and EnvironmentValues.modelContext show up in the crash report? I'm using both, but I wasn't expecting them to be a factor when running in the background.

Is anyone having a similar issue?

Accepted Answer

I think I finally figgured it out!

This Thread discusses a similar issue, it seems to be a SwiftUI bug. When the App launches in the background from being inactive, it’s crashing when an @Environment variable is used in the root ContentView (only seems to happen for .modelContext for me).

I was able to reliably reproduce it by launching the App in the background directly.

This is what I was doing:

@main
struct MyApp: App {
    var sharedModelContainer: ModelContainer = {
        // ...
    }()
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .modelContainer(sharedModelContainer)
    }
}

struct ContentView: View {
    @Environment(\.modelContext) var modelContext

    var body: some View {
        MyView()
    }
    
    func someFunc() {
        modelContext.insert(...)
    }
}

I’m now passing the container to the root view as an argument and adding it there via .modelContainer(...), which seems to have fixed the issue:

@main
struct MyApp: App {
    var sharedModelContainer: ModelContainer = {
        // ...
    }()
    
    var body: some Scene {
        WindowGroup {
            ContentView(container: sharedModelContainer)
        }
    }
}

struct ContentView: View {
    let container: ModelContainer
    
    var body: some View {
        MyView()
            .modelContainer(container)
    }
    
    func someFunc() {
        let modelContext = ModelContext(container)
        modelContext.insert(...)
    }
}

I have a similar issue where the app crashes on iOS while in the background and found this discussion via Google. Thanks for posting the solution. I will try it and confirm if it solved the issue.

Here's my crashlog:

Thread 0 name:
Thread 0 Crashed:
0   libswiftCore.dylib            	0x0000000191f758c0 _assertionFailure(_:_:file:line:flags:) + 264 (AssertCommon.swift:144)
1   libswiftCore.dylib            	0x0000000191fe3d14 swift_unexpectedError + 664 (ErrorType.swift:188)
2   _SwiftData_SwiftUI            	0x000000023368fd78 one-time initialization function for empty + 300 (ModelContainer+Extensions.swift:5)
3   libdispatch.dylib             	0x000000019b526dd4 _dispatch_client_callout + 20 (object.m:576)
4   libdispatch.dylib             	0x000000019b528654 _dispatch_once_callout + 32 (once.c:52)
5   _SwiftData_SwiftUI            	0x000000023368fdf8 one-time initialization function for empty + 124 (ModelContainer+Extensions.swift:12)
6   libdispatch.dylib             	0x000000019b526dd4 _dispatch_client_callout + 20 (object.m:576)
7   libdispatch.dylib             	0x000000019b528654 _dispatch_once_callout + 32 (once.c:52)
8   _SwiftData_SwiftUI            	0x00000002336a5170 key path getter for EnvironmentValues.modelContext : EnvironmentValues + 140 (<compiler-generated>:0)
9   libswiftCore.dylib            	0x00000001920a0628 RawKeyPathComponent._projectReadOnly<A, B, C>(_:to:endingWith:) + 1012 (KeyPath.swift:1701)
10  libswiftCore.dylib            	0x000000019209fddc KeyPath._projectReadOnly(from:) + 1036 (KeyPath.swift:331)
11  libswiftCore.dylib            	0x00000001920a4348 swift_getAtKeyPath + 24 (KeyPath.swift:2029)
12  SwiftUI                       	0x0000000197eb0814 EnvironmentBox.update(property:phase:) + 872 (Environment.swift:273)

Hi,

I encountered the same issue!

Steps to reproduce the crash:

  • Environment: iOS 17.5.1
  • Use a template project with SwiftData using CloudKit (see Code 1)
  • Install it via Testflight on two devices (A & B)
  • Add items in the CloudKit container (on a regular basis) via Device A
  • Download the App via Testflight on Device B and move the app after a few seconds to the background (not force closing the app)
  • Crash after some time

Fix: Move the .modelContainer(for: [Item.self]) ViewModifier from the WindowGroup to the ContentView.

Assumption:

  • The problem occurs when the App starts in the Background after a notification was received.
    • Maybe the WindowGroup behaves differently when started in the background, because no window exists!?
  • I could only reproduce it via a prod CloudKit environment

@DTS Engineer if that's the case, maybe the template projects in Xcode should be updated, so new projects do not trigger that crash.

Code 1 Crashing examaple:

import SwiftData
import SwiftUI

@main
struct ExampleApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .modelContainer(for: [Item.self])
    }
}

Code 2 Fixed with:

import SwiftData
import SwiftUI

@main
struct ExampleApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .modelContainer(for: [Item.self])
        }
    }
}
Error: _SwiftData_SwiftUI: one-time initialization function for empty
 
 
Q