Skip to content

[iOS]: Plugin Registration crash when adopting UISceneDelegate due to nil FlutterEngine #168228

Closed

Description

@gaaclarke

When following Apple's best practices of adopting UISceneDelegate, if the project uses any swift plugins, the project will crash at launch when plugins are registered because the objc bridge classes for swift FlutterPlugin subclasses will be nil.

I ran into this crash while trying to implement #167267, but I've also seen users in the wild running into this crash as well ( https://developer.apple.com/forums/thread/748671 ).

reproduction steps

  1. flutter create -t plugin --platform=ios swiftplugin
  2. cd swiftplugin
  3. Add the following to example/ios/Runner/Info.plist (Note that the value of the fields don't need to be valid because startup will crash before it is used).
    	<key>UIApplicationSceneManifest</key>
    	<dict>
    		<key>UIApplicationSupportsMultipleScenes</key>
    		<false/>
    		<key>UISceneConfigurations</key>
    		<dict>
    			<key>UIWindowSceneSessionRoleApplication</key>
    			<array>
    				<dict>
    					<key>UISceneClassName</key>
    					<string>UIWindowScene</string>
    					<key>UISceneDelegateClassName</key>
    					<string>$(PRODUCT_MODULE_NAME).AppDelegate</string>
    					<key>UISceneConfigurationName</key>
    					<string>flutter</string>
    					<key>UISceneStoryboardFile</key>
    					<string>Main</string>
    				</dict>
    			</array>
    		</dict>
    	</dict>
  4. cd example; flutter run

crash

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
    frame #0: 0x0000000194f85b08 libswiftCore.dylib`swift_getObjectType + 36
    frame #1: 0x000000010329935c plugintest`static PlugintestPlugin.register(registrar=__C.FlutterPluginRegistrar @ 0x000000016ce08b88) at PlugintestPlugin.swift:0
  * frame #3: 0x000000010325d834 Runner.debug.dylib`+[GeneratedPluginRegistrant registerWithRegistry:](self=GeneratedPluginRegistrant, _cmd="registerWithRegistry:", registry=0x0000600000c0daa0) at GeneratedPluginRegistrant.m:25:3
    frame #4: 0x000000010325d8c4 Runner.debug.dylib`AppDelegate.application(application=0x0000000103f05a80, launchOptions=nil) at AppDelegate.swift:10:31
    frame #6: 0x0000000185b2e30c UIKitCore`-[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 312
    frame #7: 0x0000000185b2f804 UIKitCore`-[UIApplication _callInitializationDelegatesWithActions:forCanvas:payload:fromOriginatingProcess:] + 2936
    frame #8: 0x0000000185b34984 UIKitCore`-[UIApplication _runWithMainScene:transitionContext:completion:] + 976
    frame #9: 0x00000001851405ec UIKitCore`-[_UISceneLifecycleMultiplexer completeApplicationLaunchWithFBSScene:transitionContext:] + 148
    frame #10: 0x0000000185b316b0 UIKitCore`-[UIApplication _compellApplicationLaunchToCompleteUnconditionally] + 44
    frame #11: 0x0000000185b319b8 UIKitCore`-[UIApplication _run] + 760
    frame #12: 0x0000000185b35bd4 UIKitCore`UIApplicationMain + 124
    frame #13: 0x0000000184f0a334 UIKitCore`UIKit.UIApplicationMain(Swift.Int32, Swift.Optional<Swift.UnsafeMutablePointer<Swift.UnsafeMutablePointer<Swift.Int8>>>, Swift.Optional<Swift.String>, Swift.Optional<Swift.String>) -> Swift.Int32 + 100
    frame #16: 0x000000010325de10 Runner.debug.dylib`main at <compiler-generated>:0
    frame #17: 0x0000000103009410 dyld_sim`start_sim + 20
    frame #18: 0x00000001030d6b4c dyld`start + 6000

Inspecting the type in the debugger after the crash looks like this:

(lldb) po PlugintestPlugin.self
note: error: No module map file in /Users/aaclarke/Library/Developer/Xcode/DerivedData/Runner-akumchbkelcnzlcblbxzpccssdcp/Build/Products/Debug-iphonesimulator/Flutter.framework
error: Error [IRForTarget]: Couldn't resolve the class for an Objective-C static method call

doctor

[!] Flutter (Channel [user-branch], 3.32.0-1.0.pre.382, on macOS 15.4.1 24E263 darwin-arm64, locale en) [551ms]
    ! Flutter version 3.32.0-1.0.pre.382 on channel [user-branch] at /Users/aaclarke/dev/flutter
      Currently on an unknown channel. Run `flutter channel` to switch to an official channel.
      If that doesn't fix the issue, reinstall Flutter by following instructions at https://flutter.dev/setup.
    ! Upstream repository unknown source is not a standard remote.
      Set environment variable "FLUTTER_GIT_URL" to unknown source to dismiss this error.
    • Framework revision 448e3036e0 (28 minutes ago), 2025-05-02 09:38:10 -0700
    • Engine revision 9ffc2d9ef3
    • Dart version 3.9.0 (build 3.9.0-76.0.dev)
    • DevTools version 2.46.0-dev.0
    • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and upgrades.

[!] Android toolchain - develop for Android devices (Android SDK version 35.0.0-rc4) [1,093ms]
    • Android SDK at /Users/aaclarke/Library/Android/sdk
    • Emulator version 35.2.10.0 (build_id 12414864) (CL:N/A)
    • Platform android-35, build-tools 35.0.0-rc4
    • Java binary at: path/to/jdk/bin/java
      This JDK is specified in your Flutter configuration.
      To change the current JDK, run: `flutter config --jdk-dir="path/to/jdk"`.
    ✗ Cannot execute path/to/jdk/bin/java to determine the version

[!] Xcode - develop for iOS and macOS (Xcode 16.3) [1,107ms]
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 16E140
    ! CocoaPods 1.15.2 out of date (1.16.2 is recommended).
        CocoaPods is a package manager for iOS or macOS platform code.
        Without CocoaPods, plugins will not work on iOS or macOS.
        For more info, see https://flutter.dev/to/platform-plugins
      To update CocoaPods, see https://guides.cocoapods.org/using/getting-started.html#updating-cocoapods

[✓] Chrome - develop for the web [7ms]
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2024.2) [7ms]
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 21.0.3+-79915917-b509.11)

[✓] VS Code (version 1.99.3) [4ms]
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.110.0

[✓] Connected device (4 available) [6.3s]
    • iPhone (5) (wireless) (mobile) • 00008110-001524D40A10401E            • ios            • iOS 18.4.1 22E252
    • iPhone 16 Pro (mobile)         • 9DA578E6-E85A-44FA-9673-D01C31F3B779 • ios            • com.apple.CoreSimulator.SimRuntime.iOS-18-2 (simulator)
    • macOS (desktop)                • macos                                • darwin-arm64   • macOS 15.4.1 24E263 darwin-arm64
    • Chrome (web)                   • chrome                               • web-javascript • Google Chrome 135.0.7049.116

[✓] Network resources [152ms]
    • All expected network resources are available.

Activity

  1. gaaclarke commented on May 2, 2025

    @gaaclarke
    MemberAuthor

    @stuartmorgan-g is this a failure that we've run into in other circumstances with swift plugins where we are able to compile fine but at runtime the bridge classes are nil?

  2. gaaclarke commented on May 2, 2025

    @gaaclarke
    MemberAuthor

    As an experiment I moved the +[GeneratedPluginRegistrant registerWithRegistry:] call later in the app startup with a "dispatch after" and the crash still happened. The theory was maybe that was too early in app startup and the bridge wasn't initialized yet, but that doesn't seem to be the case.

  3. gaaclarke commented on May 2, 2025

    @gaaclarke
    MemberAuthor

    Jenn question if when it prints something like

    No module map file in /Users/aaclarke/Library/Developer/Xcode/DerivedData/Runner-gnymzorfhvfvixdrpycicrjdhpnl/Build/Products/Debug-iphonesimulator/Flutter.framework
    

    is there a module map there? There is (albeit in a Modules subdirectory).

    $ cat /Users/aaclarke/Library/Developer/Xcode/DerivedData/Runner-gnymzorfhvfvixdrpycicrjdhpnl/Build/Products/Debug-iphonesimulator/Flutter.framework/Modules/module.modulemap
    framework module Flutter {
      umbrella header "Flutter.h"
    
      export *
      module * { export * }
    }
    
  4. gaaclarke commented on May 2, 2025

    @gaaclarke
    MemberAuthor

    Here is a similar crash where the user claimed it only happened in testflight: https://stackoverflow.com/questions/77206289/flutter-runs-locally-but-testflight-build-crashes-on-swift-getobjecttype

    I tried adding the linker flags -ObjC and -all_load to the example target to see if the objc bridge code was being dropped by the linker, but that didn't fix it.

  5. gaaclarke commented on May 2, 2025

    @gaaclarke
    MemberAuthor

    I tried switching to swift package manager and it doesn't resolve the crash.

  6. gaaclarke commented on May 2, 2025

    @gaaclarke
    MemberAuthor

    So in the reproduction above, the crash happens when attempting to use the SwiftpluginPlugin class in the swiftplugin package.

    At the crash you can see the swiftplugin.framework is loaded:

    (lldb) image list | grep swiftplugin
    [  0] 75260E8D-37F9-3F0B-BC5C-BEF63D27EF59 0x000000010108c000 /Users/aaclarke/Library/Developer/Xcode/DerivedData/Runner-gnymzorfhvfvixdrpycicrjdhpnl/Build/Products/Debug-iphonesimulator/Runner.app/Frameworks/swiftplugin.framework/swiftplugin 
    

    I expect the symbols for the objc classes to exist in that binary, they do appear.

    nm /Users/aaclarke/Library/Developer/Xcode/DerivedData/Runner-gnymzorfhvfvixdrpycicrjdhpnl/Build/Products/Debug-iphonesimulator/swiftplugin/swiftplugin.framework/swiftplugin | grep SwiftpluginPlugin
    0000000000001484 T _$s11swiftplugin17SwiftpluginPluginC6handle_6resultySo17FlutterMethodCallC_yypSgctF
    0000000000001748 t _$s11swiftplugin17SwiftpluginPluginC6handle_6resultySo17FlutterMethodCallC_yypSgctFTo
    0000000000003ee4 S _$s11swiftplugin17SwiftpluginPluginC6handle_6resultySo17FlutterMethodCallC_yypSgctFTq
    00000000000011e8 T _$s11swiftplugin17SwiftpluginPluginC8register4withySo07FlutterC9Registrar_p_tFZ
    0000000000001434 t _$s11swiftplugin17SwiftpluginPluginC8register4withySo07FlutterC9Registrar_p_tFZTo
    0000000000001410 T _$s11swiftplugin17SwiftpluginPluginCACycfC
    00000000000018f8 T _$s11swiftplugin17SwiftpluginPluginCACycfc
    0000000000001974 t _$s11swiftplugin17SwiftpluginPluginCACycfcTo
    0000000000003eec s _$s11swiftplugin17SwiftpluginPluginCMF
    00000000000013ec T _$s11swiftplugin17SwiftpluginPluginCMa
    000000000000c8b8 s _$s11swiftplugin17SwiftpluginPluginCMf
    0000000000003eb0 S _$s11swiftplugin17SwiftpluginPluginCMn
    000000000000c8d0 S _$s11swiftplugin17SwiftpluginPluginCN
    0000000000001994 T _$s11swiftplugin17SwiftpluginPluginCfD
    000000000000c8d0 S _OBJC_CLASS_$__TtC11swiftplugin17SwiftpluginPlugin
    000000000000c940 D _OBJC_METACLASS_$__TtC11swiftplugin17SwiftpluginPlugin
    0000000000002c70 s __CLASS_METHODS__TtC11swiftplugin17SwiftpluginPlugin
    000000000000c870 s __DATA__TtC11swiftplugin17SwiftpluginPlugin
    0000000000002c88 s __INSTANCE_METHODS__TtC11swiftplugin17SwiftpluginPlugin
    000000000000c100 s __METACLASS_DATA__TtC11swiftplugin17SwiftpluginPlugin
    000000000000c0f0 s __PROTOCOLS__TtC11swiftplugin17SwiftpluginPlugin
    000000000000c148 s __PROTOCOLS__TtC11swiftplugin17SwiftpluginPlugin.1
    0000000000003e8c s _symbolic _____ 11swiftplugin17SwiftpluginPluginC
    

    I am able to resolve the class with NSClassFromString, however :

    (lldb) p (Class)NSClassFromString(@"swiftplugin.SwiftpluginPlugin")
    (Class) swiftplugin.SwiftpluginPlugin
    

    That means we know the symbols is present in the binaries and it can be loaded, but for some reason [SwiftpluginPlugin class] is not working. This makes it sound like the magic that appends the module name is not working. That may be the module map that is referenced in the error message?

  7. gaaclarke commented on May 2, 2025

    @gaaclarke
    MemberAuthor

    Editing the GeneratedPluginRegistrant to do NSLog(@"%@", [SwiftpluginPlugin class]); works, it prints out swiftplugin.SwiftpluginPlugin, correctly mapping the name to module+name. This is weird because it didn't work when invoked from lldb. This also means my theory that we don't have the information to map from name to module+name is incorrect.

  8. gaaclarke commented on May 2, 2025

    @gaaclarke
    MemberAuthor

    Looking at the stacktrace again. It appears we are loading the register function fine. I got on a bit of a rabbit chase because po [SwiftpluginPlugin class] didn't work in lldb.

  9. gaaclarke commented on May 2, 2025

    @gaaclarke
    MemberAuthor

    Okay, I think I've track down the root of the problem. SwiftpluginPlugin.register is called with a nil registrar. I don't know for the life of me why all of the messages I got from lldb didn't clearly state that. The plist item is rearranging the startup somehow so that that was previously already initialized, now it isn't.

  10. hellohuanlin commented on May 9, 2025

    @hellohuanlin
    Contributor

    Okay, I think I've track down the root of the problem. SwiftpluginPlugin.register is called with a nil registrar. I don't know for the life of me why all of the messages I got from lldb didn't clearly state that. The plist item is rearranging the startup somehow so that that was previously already initialized, now it isn't.

    Sounds like this is the same problem as described in the design doc, and it's unrelated to Swift?

  11. gaaclarke commented on May 9, 2025

    @gaaclarke
    MemberAuthor

    Sounds like this is the same problem as described in the design doc, and it's unrelated to Swift?

    Yes, it turned to to be unrelated to swift. It just happened to show up in our swift tests because the objc tests would noop when it encountered a nil, swift gave us a crash in swift_getObjectType.

  12. changed the title [-][iOS]: Swift plugins crash when adopting UISceneDelegate[/-] [+][iOS]: Plugin Registration crash when adopting UISceneDelegate due to nil FlutterEngine[/+] on May 14, 2025
  13. added
    platform-iosiOS applications specifically
    c: fatal crashCrashes that terminate the process
    P1High-priority issues at the top of the work list
    triaged-iosTriaged by iOS platform team
    on May 22, 2025
  14. damengzai commented on Jun 4, 2025

    @damengzai

    try newest master branch 3.33.+,I have similar bug by flutter stable 3.32.1,but 3.33.+ is ok.

  15. gaaclarke commented on Jun 4, 2025

    @gaaclarke
    MemberAuthor

    fixed in #169365

  16. github-actions commented on Jun 18, 2025

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  17. locked as resolved and limited conversation to collaborators on Jun 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High-priority issues at the top of the work listc: fatal crashCrashes that terminate the processplatform-iosiOS applications specificallyteam-iosOwned by iOS platform teamtriaged-iosTriaged by iOS platform team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions