Skip to content

[Bug]: iOS crash on Flutter 3.41 UIScene lifecycle: BGTaskScheduler registration happens after application finished launching #414

@drakeet

Description

@drakeet

Required Reading

  • Confirmed

Plugin Version

1.3.8

Flutter Doctor

N/A

Mobile operating-system(s)

  • iOS
  • Android

Device Manufacturer(s) and Model(s)

iOS 18.3.1

Device operating-systems(s)

iOS 18.3.1

What happened?

Hi, thanks for maintaining background_fetch.

We recently upgraded our Flutter app from Flutter 3.38 to Flutter 3.41.6 stable. After that upgrade, we started seeing a fatal iOS startup crash from background_fetch on iOS 18.3.1:

Fatal Exception: NSInternalInconsistencyException
0  CoreFoundation                 __exceptionPreprocess
1  libobjc.A.dylib                objc_exception_throw
2  Foundation                     _userInfoForFileAndLine
3  BackgroundTasks                -[BGTaskScheduler _unsafe_registerForTaskWithIdentifier:usingQueue:launchHandler:]
4  BackgroundTasks                -[BGTaskScheduler registerForTaskWithIdentifier:usingQueue:launchHandler:]
5  background_fetch               -[TSBackgroundFetch registerAppRefreshTask]
6  background_fetch               -[TSBackgroundFetch didFinishLaunching]
7  background_fetch               -[BackgroundFetchPlugin application:didFinishLaunchingWithOptions:] + 36 (BackgroundFetchPlugin.m:36)
8  Flutter                        -[FlutterPluginAppLifeCycleDelegate application:didFinishLaunchingWithOptions:isFallbackForScene:]
9  Flutter                        -[FlutterPluginAppLifeCycleDelegate application:didFinishLaunchingWithOptions:]
10 Flutter                        -[FlutterPluginAppLifeCycleDelegate sceneFallbackDidFinishLaunchingApplication:]
11 Flutter                        -[FlutterViewController sharedSetupWithProject:initialRoute:]
12 Flutter                        -[FlutterViewController awakeFromNib]

Environment:

Flutter 3.41.6 stable
Dart 3.11.4
background_fetch 1.3.8 when the crash was observed
iOS 18.3.1
App has adopted Flutter 3.41 UIScene lifecycle

Our iOS app follows Flutter's UIScene migration guidance:

@main
@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }

  func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {
    GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)
  }
}

Info.plist uses UIApplicationSceneManifest with a FlutterSceneDelegate subclass.

From the stack trace, it looks like the plugin receives application:didFinishLaunchingWithOptions: via Flutter's sceneFallbackDidFinishLaunchingApplication path after the implicit engine / FlutterViewController has been initialized from the scene. At that point, TSBackgroundFetch calls BGTaskScheduler.registerForTaskWithIdentifier, but iOS requires all BGTaskScheduler launch handlers to be registered before application launch finishes. This can trigger the system exception:

All launch handlers must be registered before application finishes launching

We upgraded to background_fetch 1.5.1 to test, but the plugin source still appears to register TSBackgroundFetch from the AppDelegate lifecycle callback:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [[TSBackgroundFetch sharedInstance] didFinishLaunching];
    return YES;
}

Possible fix:

Please consider making the iOS plugin compatible with Flutter 3.41's UIScene lifecycle. Specifically, BGTaskScheduler.register(...) / TSBackgroundFetch.didFinishLaunching likely needs to be called early enough in the real app launch process, before UIKit considers application launch finished, instead of relying only on the Flutter plugin application lifecycle fallback that may be delivered from the scene path.

It may also be worth documenting the Flutter 3.41 UIScene interaction and the recommended AppDelegate / SceneDelegate setup for apps using background_fetch.

Thank you.

Plugin Code and/or Config

N/A

Relevant log output

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions