Skip to content

[firebase_messaging]: 16.5.0 skips registerForRemoteNotifications at launch when Firebase is initialized from Dart (regression from #18452, not covered by #18620) #18643

Description

@fukazayo

Is there an existing issue for this?

  • I have searched the existing issues.

Which plugins are affected?

Messaging

Which platforms are affected?

iOS

Description

Since 16.5.0, apps that initialize Firebase from Dart (Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform), no GoogleService-Info.plist, no native FirebaseApp.configure()) never register for remote notifications at launch. As a result:

  • FirebaseMessaging.instance.getAPNSToken() stays null indefinitely on every launch (polled at 0 / 3 / 10 / 30 s).
  • getToken() throws [firebase_messaging/apns-token-not-set].
  • onTokenRefresh never fires.
  • The only remaining path that calls registerForRemoteNotifications is a permission request (e.g. via permission_handler), which is asynchronous, so the first getToken() right after the user grants permission races the APNs round-trip and loses most of the time. A device that already granted permission never registers again on relaunch.

The same app works on 16.4.3 (identical setup, only the plugin version differs).

Root cause

#18452 (shipped in 16.5.0) changed the launch-time registration in setupNotificationHandlingWithRemoteNotification: from an unconditional call to:

if ([FIRMessaging messaging].isAutoInitEnabled) {
  [self registerForRemoteNotifications];
}

When Firebase is initialized from Dart, this runs before FirebaseApp.configure() has happened. +[FIRMessaging messaging] calls [FIRApp defaultApp], which logs I-COR000003 The default Firebase app has not yet been configured and returns nil, so FIR_COMPONENT(FIRMessagingInterop, nil.container) is nil and nil.isAutoInitEnabled evaluates to NO. Registration is skipped on every launch, and nothing re-runs it once Firebase is configured (didReinitializeFirebaseCore: in the messaging plugin is a no-op).

Dart-side initialization is a configuration this plugin explicitly supported before: #7754 was fixed by #7610 ("Set APNS token if user initializes Firebase app from Flutter"), which is why 16.4.3 works.

Why #18620 does not fix it

#18620 runs setupNotificationHandlingWithRemoteNotification: immediately at plugin registration when a scene is already connected. That fixes the missed-callback ordering, but the isAutoInitEnabled gate above is still evaluated before Firebase is configured. I applied the #18620 diff on top of 16.5.0 (local path override) and added an NSLog right before the gate:

[18620-PROBE] scene already connected at plugin registration, running setup now
[18620-PROBE] setup: FIRMessaging=nil isAutoInitEnabled=0
[TOKEN-PROBE] apns token not set within 30s

Setup ran, the gate was NO, and no APNs token arrived within 30 s.

Workaround

Calling FirebaseMessaging.instance.setAutoInitEnabled(true) on iOS right after Firebase.initializeApp(). messagingSetAutoInitEnabled: calls registerForRemoteNotifications and ensureAPNSTokenSetting unconditionally when enabled == YES. With that, the APNs token arrives ~0.8 s after launch, before the user reaches the permission prompt.

Suggested fix

Re-evaluate the auto-init gate once Firebase core is actually configured, for example in didReinitializeFirebaseCore: (call registerForRemoteNotifications there when [FIRMessaging messaging].isAutoInitEnabled is YES), or resolve the auto-init flag without requiring a FIRApp instance (Info.plist FirebaseMessagingAutoInitEnabled / the persisted user default). Either restores the 16.4.3 behaviour for Dart-initialized apps while keeping the opt-in semantics #18452 intended.

Reproducing the issue

  1. Take any Flutter app that initializes Firebase from Dart: firebase_options.dart generated by flutterfire configure, Firebase.initializeApp(options: ...) in main(), no GoogleService-Info.plist in the iOS project, no native FirebaseApp.configure(). Method swizzling enabled (default). FirebaseMessagingAutoInitEnabled not set (defaults to enabled).
  2. firebase_messaging: 16.5.0 (also reproduces on 16.6.0 and main).
  3. After Firebase.initializeApp(), poll FirebaseMessaging.instance.getAPNSToken() every second for 30 s.
  4. Observe null for the whole period, and getToken() throwing apns-token-not-set. Watch the unified log for the I-COR000003 lines emitted at plugin setup.
  5. Pin firebase_messaging: 16.4.3 (and the matching firebase_core 4.12.1 so the Firebase iOS SDK pins agree): the APNs token arrives within ~1 s of launch.

Reproduces on an Apple silicon simulator (iPhone 17, iOS 26.5, which supports APNs) and on physical devices. UIScene vs. non-UIScene does not matter for this case.

Firebase Core version

4.13.0 (firebase_core_platform_interface 8.1.0, Firebase iOS SDK 12.17.0)

Flutter Version

3.44.9 (Dart 3.12.2), Xcode 26.6

Relevant Log Output

# at plugin setup (before Dart-side Firebase.initializeApp() completes)
[FirebaseCore][I-COR000012] Could not locate configuration file: 'GoogleService-Info.plist'.
[FirebaseCore][I-COR000003] The default Firebase app has not yet been configured. Add `FirebaseApp.configure()` to your application initialization. ...
[FirebaseCore][I-COR000003] The default Firebase app has not yet been configured. ...

# ~0.7 s later, Dart-side initialization completes
[FirebaseMessaging][I-FCM001000] FIRMessaging Remote Notifications proxy enabled, will swizzle remote notification receiver handlers. ...

# Dart-side probe, same launch
[TOKEN-PROBE] probe t=0s apns=null
[TOKEN-PROBE] probe t=3s apns=null
[TOKEN-PROBE] probe t=10s apns=null
[TOKEN-PROBE] probe t=30s apns=null

# getToken() right after the user grants permission (permission_handler)
[TOKEN-PROBE] update() start apns=null
[TOKEN-PROBE] update() getToken threw apns-token-not-set: APNS token has not been received on the device yet. Please ensure the APNS token is available before calling `getAPNSToken()`.

Flutter dependencies

Expand Flutter dependencies snippet
firebase_core: ^4.6.0            # resolved 4.13.0
firebase_messaging: ^16.5.0      # resolved 16.5.0
firebase_analytics: ^12.4.6
firebase_crashlytics: ^5.2.7
firebase_remote_config: ^6.5.6
permission_handler: ^13.0.0      # used for the notification permission prompt

Additional context and comments

  • +[FIRMessaging messaging] returning nil before configure: FIRMessaging.m[FIRApp defaultApp]FIR_COMPONENT(FIRMessagingInterop, defaultApp.container); +[FIRApp defaultApp] logs I-COR000003 and returns nil when sDefaultApp is unset.
  • The 16.5.0 → 16.6.0 iOS plugin diff only touches the macOS launch payload handling, so 16.6.0 is affected as well.
  • Happy to test a patch on this setup.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions