Skip to content

[firebase_messaging] setForegroundNotificationPresentationOptions causes EXC_BAD_ACCESS on iOS during App Store review #18282

@tectics2020-svg

Description

@tectics2020-svg

Is there an existing issue for this?

  • I have searched the existing issues.

Which plugins are affected?

Messaging

Which platforms are affected?

iOS

Description

Calling FirebaseMessaging.instance.setForegroundNotificationPresentationOptions() from Dart consistently triggers a native EXC_BAD_ACCESS (SIGSEGV) crash on iOS. The crash originates inside the Firebase Messaging plugin's native iOS layer and cannot be caught by Dart try/catch. Apple App Store review has rejected three consecutive builds (build numbers 15, 16, 17) with the same crash signature.

The crash occurs regardless of whether the call is wrapped in try/catch or guarded by an initialization flag.

Steps to reproduce

  1. Configure a Flutter app with firebase_messaging: 16.1.0 and iOS deployment target 16.0.

  2. Add remote-notification background mode to the iOS app.

  3. Use FlutterAppDelegate in AppDelegate.swift.

  4. From a WidgetsBindingObserver, call setForegroundNotificationPresentationOptions when the app resumes:

    void clearIOSBadge() {
      FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
        alert: true,
        badge: false,
        sound: true,
      );
      Future.delayed(const Duration(seconds: 1), () {
        FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
          alert: true,
          badge: true,
          sound: true,
        );
      });
    }
    
    @override
    void didChangeAppLifecycleState(AppLifecycleState state) {
      if (state == AppLifecycleState.resumed) {
        clearIOSBadge();
      }
    }
  5. Submit the build to Apple App Store review (or run on a clean iOS device where the app has just been installed).

Expected behavior

setForegroundNotificationPresentationOptions should either complete successfully or throw a catchable Dart exception. It should not cause a native EXC_BAD_ACCESS crash.

Observed behavior

  • Crash signal: EXC_BAD_ACCESS (SIGSEGV)
  • Crash thread: native iOS, inside Firebase Messaging plugin
  • Three consecutive Apple App Store review rejections with identical crash signature
  • Dart try/catch does not intercept the crash (expected, since it is native)
  • An _isInitialized guard added before the call did not prevent the crash
  • The crash does not reproduce reliably during local development; it surfaces consistently in Apple's review environment

Sample project

The minimal reproduction is the code block above. The crash is observed in a production app; we can prepare a minimal repro project on request.


Additional context

Purpose of the call

The pattern (toggle badge: false then badge: true after 1 second) is widely referenced in the community as a workaround for clearing the iOS app icon badge in FCM-based Flutter apps, since firebase_messaging does not expose a direct badge-clearing API.

Related Apple documentation

UIApplication.applicationIconBadgeNumber is deprecated as of iOS 17 in favor of UNUserNotificationCenter.current().setBadgeCount(_:). The interaction between setForegroundNotificationPresentationOptions and the deprecated badge API is not documented in the FlutterFire plugin reference.

Workaround currently in production

All calls to setForegroundNotificationPresentationOptions have been disabled. The app passes Apple review but the iOS app icon badge never clears.

Questions for maintainers

  1. Is this crash known and tracked elsewhere in the repo? (I searched issues but could not find a matching report.)
  2. Does setForegroundNotificationPresentationOptions have an undocumented precondition (initialization order, call frequency, threading) that the code above violates?
  3. Is calling UNUserNotificationCenter.current().setBadgeCount(0) directly in AppDelegate.swift (alongside FlutterAppDelegate's lifecycle handling) a supported pattern, or does it conflict with FCM's internal notification handling?

Flutter doctor

Output of flutter doctor -v
[paste flutter doctor -v output here]

Flutter dependencies

Output of flutter pub deps -- --style=compact
[paste flutter pub deps --style=compact output here]

Reproducing the issue

Steps:

  1. Configure a Flutter app with firebase_messaging: 16.1.0 and iOS deployment target 16.0.
  2. Add remote-notification background mode to the iOS app.
  3. Use FlutterAppDelegate in AppDelegate.swift.
  4. Call setForegroundNotificationPresentationOptions from a lifecycle observer when the app resumes:
void clearIOSBadge() {
  FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
    alert: true,
    badge: false,
    sound: true,
  );
  Future.delayed(const Duration(seconds: 1), () {
    FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
      alert: true,
      badge: true,
      sound: true,
    );
  });
}

@override
void didChangeAppLifecycleState(AppLifecycleState state) {
  if (state == AppLifecycleState.resumed) {
    clearIOSBadge();
  }
}
  1. Submit the build to Apple App Store review.

The pattern (toggle badge: false then badge: true after 1 second) is widely referenced as a workaround for clearing the iOS app icon badge in FCM-based Flutter apps, since firebase_messaging does not expose a direct badge-clearing API.

Firebase Core version

4.3.0

Flutter Version

3.38.5

Relevant Log Output

firebase_core: 4.3.0
firebase_messaging: 16.1.0
firebase_auth: 6.1.3
cloud_firestore: [확인 필요시 알려주세요]
firebase_storage: 13.0.5

Flutter dependencies

Details [√] Flutter (Channel stable, 3.38.5, on Microsoft Windows [Version 10.0.19045.6456], locale ko-KR) • Flutter version 3.38.5 on channel stable at D:\dev\flutter • Framework revision f6ff1529fd (5 months ago), 2025-12-11 • Engine revision 1527ae0ec5 • Dart version 3.10.4 • DevTools version 2.51.1

[√] Windows Version (10 Home 64-bit, 22H2, 2009)

[!] Android toolchain - develop for Android devices (Android SDK version 36.1.0)
• Android SDK at D:\Android\Sdk
• Emulator version 36.3.10.0
X cmdline-tools component is missing.
X Android license status unknown.

[√] Chrome - develop for the web

[X] Visual Studio - develop Windows apps (not installed — not relevant for iOS bug)

[√] Connected device (4 available)
• SM G965N (mobile) • Android 10 (API 29)
• Windows (desktop)
• Chrome (web)
• Edge (web)

[√] Network resources

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions