Skip to content

[firebase_messaging][iOS] getToken intermittently takes 3.5–6s force-close during startup token flow can lead to prolonged no-push state #18209

@yangheecho

Description

@yangheecho

Is there an existing issue for this?

  • I have searched the existing issues.

Which plugins are affected?

Messaging

Which platforms are affected?

iOS

Description

After migrating iOS to UIScene (FlutterImplicitEngineDelegate + UIApplicationSceneManifest),
Correction: In our case, this does not appear to be strictly UIScene-migration-specific.

What changed on our side is the Flutter upgrade:

  • Flutter was upgraded from 3.35.2 to 3.41.6.
  • Current project Flutter version is 3.41.6 (.fvmrc / .fvm_config.json).

From our observations, the issue started after this Flutter version upgrade window.

FirebaseMessaging.getToken() frequently takes 3500ms ~ 6000ms (more than ~50% of cold starts in our testing).
During repeated launch/force-close cycles, push delivery can enter a broken state (foreground/background/terminated all not receiving), and in some sessions onTokenRefresh does not fire even after long foreground wait.

APNs registration is usually fast, but getToken() latency is highly variable and seems to correlate with the no-push state.

Reproducing the issue

  1. Fresh install (or clear app data).
  2. Launch app on iOS physical device and allow notification permission.
  3. Startup calls (async):
    • iOS: wait for getAPNSToken()
    • then call getToken()
  4. While getToken() is still pending (slow case), force-close the app.
  5. Relaunch and test push delivery.
  6. Result: push may stop arriving in all states (foreground/background/terminated).

Code sample (sanitized)

Future<void> initializeFcmTokenLifecycle() async {
  await Firebase.initializeApp();
  await FirebaseMessaging.instance.setAutoInitEnabled(true);

  final settings = await FirebaseMessaging.instance.requestPermission(
    alert: true,
    badge: true,
    sound: true,
    provisional: false,
  );
  final isAuthorized =
      settings.authorizationStatus == AuthorizationStatus.authorized ||
      settings.authorizationStatus == AuthorizationStatus.provisional;
  if (!isAuthorized) return;

  FirebaseMessaging.instance.onTokenRefresh.listen((newToken) async {
    await secureStorage.saveFCMToken(newToken);
    await sendWelcome(pushToken: newToken); // backend token sync
  });

  if (Platform.isIOS) {
    final deadline = DateTime.now().add(const Duration(seconds: 8));
    while (DateTime.now().isBefore(deadline)) {
      final apns = await FirebaseMessaging.instance.getAPNSToken();
      if (apns != null && apns.isNotEmpty) break;
      await Future.delayed(const Duration(milliseconds: 100));
    }
  }

  final stopwatch = Stopwatch()..start();
  final token = await FirebaseMessaging.instance.getToken();
  logger('getToken elapsedMs=${stopwatch.elapsedMilliseconds} token=$token');
}
@main
@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    UNUserNotificationCenter.current().delegate = self
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }

  override func application(
    _ application: UIApplication,
    didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
  ) {
    Messaging.messaging().apnsToken = deviceToken
    super.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
  }
}

In affected sessions, previously used tokens return server-side errors such as ApnsError(BadDeviceToken, INVALID_ARGUMENT) and FcmError(UNREGISTERED, NOT_FOUND).

Log Output

1) APNs registration is stable/fast (not the bottleneck)

Across multiple launches, APNs token stays the same and registration callback is fast (~95-100ms after first launch):

[2026-04-20T08:02:31Z] didRegisterForRemoteNotificationsWithDeviceToken length=32 elapsedMs=815 token=35f8cee6...ceb19cac(64)
[2026-04-20T08:02:44Z] didRegisterForRemoteNotificationsWithDeviceToken length=32 elapsedMs=95 token=35f8cee6...ceb19cac(64)
[2026-04-20T08:02:51Z] didRegisterForRemoteNotificationsWithDeviceToken length=32 elapsedMs=98 token=35f8cee6...ceb19cac(64)

2) Normal startup case: getToken returns in ~2.0s and refresh path syncs

This is a successful/healthy cycle:

[2026-04-20T08:02:33.459716Z] [main.fcm.fetch] startup getFCMToken start
[2026-04-20T08:02:33.460255Z] [main.fcm.fetch] apns ready token=35F8CEE6...9CAC(64) elapsedMs=0
[2026-04-20T08:02:35.520007Z] [FirebaseService.getFCMToken] token success=fa4isv8F...nOTQ(142) elapsedMs=2059
[2026-04-20T08:02:35.522910Z] [main.fcm.update] source=onTokenRefresh saved=fa4isv8F...nOTQ(142)
[2026-04-20T08:02:35.608702Z] [main.fcm.update] source=onTokenRefresh welcome sync done

3) Slow startup case: getToken takes ~4.7s and token rotates

This shows high latency and token change in another cycle:

[2026-04-20T08:02:51.791883Z] [main.fcm.fetch] startup getFCMToken start
[2026-04-20T08:02:51.793125Z] [main.fcm.fetch] apns ready token=35F8CEE6...9CAC(64) elapsedMs=1
[2026-04-20T08:02:56.491239Z] [FirebaseService.getFCMToken] token success=fa4isv8F...YMOo(142) elapsedMs=4696
[2026-04-20T08:02:56.495063Z] [main.fcm.update] source=onTokenRefresh saved=fa4isv8F...YMOo(142)
[2026-04-20T08:02:56.527137Z] [main.fcm.update] source=onTokenRefresh welcome sync done

4) Problematic window: getToken started but no success line in this capture

This is the key evidence for "started token flow but no completion observed" (e.g., force-close/interruption window):

[2026-04-20T08:03:02.565053Z] [main.fcm.fetch] startup getFCMToken start
[2026-04-20T08:03:02.565753Z] [main.fcm.fetch] apns ready token=35F8CEE6...9CAC(64) elapsedMs=0
(no matching `FirebaseService.getFCMToken token success` after this in this log capture)

Firebase Core version

4.7.0

Flutter Version

3.41.6

Relevant Log Output

Flutter dependencies

Expand Flutter dependencies snippet
firebase_messaging: 16.2.0
firebase_messaging_platform_interface: 4.7.9
firebase_core: 4.7.0
firebase_core_platform_interface: 6.0.3

Additional context and comments

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    blocked: customer-responseWaiting for customer response, e.g. more information was requested.platform: iosIssues / PRs which are specifically for iOS.plugin: messagingtype: bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions