Skip to content

[firebase_messaging] iOS: plugin answers willPresent for notifications it does not own, silently dropping local notifications #18716

Description

@terekhovm

Is there an existing issue for this?

  • I have searched the existing issues.

Which plugins are affected?

Messaging

Which platforms are affected?

iOS

Description

On iOS, FLTFirebaseMessagingPlugin calls the UNUserNotificationCenter completion handler for
every foreground notification, including notifications created by other plugins. Since the
default presentation options are empty, iOS drops those notifications: nothing is shown and
they are not even stored as delivered. No error surfaces anywhere — show() succeeds.

This happens whenever the app has a UNUserNotificationCenterDelegate that conforms to
FlutterAppLifeCycleProvider, i.e. any FlutterAppDelegate, because the plugin then keeps
_originalNotificationCenterDelegate nil:

    if ([currentDelegate conformsToProtocol:@protocol(FlutterAppLifeCycleProvider)]) {
      shouldReplaceDelegate = NO;
    }

and later takes the else branch of willPresentNotification: regardless of whose notification
it is:

    } else {
      UNNotificationPresentationOptions presentationOptions = UNNotificationPresentationOptionNone;
      NSDictionary *persistedOptions = ...;
      ...
      completionHandler(presentationOptions);
    }

The gcm.message_id check above is only used to emit Messaging#onMessage, not for the
presentation decision.

flutter_local_notifications handles the same situation correctly and leaves the completion
handler alone when the notification is not its own:

    if (![self isAFlutterLocalNotification:notification.request.content.userInfo]) {
      return;
    }

Suggested fix: return early from willPresentNotification: when gcm.message_id is absent and the
plugin has not replaced the delegate, leaving the decision to the owner of the notification.

Both code paths are old — the conformsToProtocol check first shipped in 11.4.2 (June 2022) and
the unconditional completionHandler call exists at least since 9.0.0 (February 2021). What
changed is the UIScene lifecycle, default since Flutter 3.41.

Reproducing the issue

Minimal reproduction, no Firebase project or credentials required:
https://github.com/terekhovm/fcm_issue

  1. flutter run on an iOS device
  2. allow notifications
  3. keep the app in the foreground and press "Show local notification"

Expected: a banner appears, the screen reports "delivered notifications: 1".
Actual: nothing appears, the screen reports "delivered notifications: 0".

Removing firebase_messaging from pubspec.yaml — nothing else — makes it work.

The app is a stock flutter create project plus the single line that
flutter_local_notifications' iOS setup asks for.

Firebase Core version

4.15.0

Flutter Version

3.47.5

Relevant Log Output

No output: show() returns successfully and nothing is logged on either side.

Flutter dependencies

firebase_core: ^4.15.0
firebase_messaging: ^16.7.0
flutter_local_notifications: ^22.3.1

Additional context and comments

Related but different: #18204 was closed as a plugin version issue, and
flutter/flutter#185048 as the same. Neither covers the plugin answering for foreign
notifications.

Workaround for apps hitting this: answer in the app's own AppDelegate — handle local
notifications there and forward remote ones to super so Messaging#onMessage keeps firing.

Activity

  1. SelaseKay commented on Sep 24, 2026

    @SelaseKay
    Contributor

    Hi @terekhovm, thanks for the report. I'm looking into it.

  2. SelaseKay commented on Sep 24, 2026

    @SelaseKay
    Contributor

    Hi @terekhovm, thanks for the write-up and the repro.

    This is the same bug as #18699. When AppDelegate owns UNUserNotificationCenter, willPresentNotification: still calls the shared completion handler. With no presentation options saved, that call is UNNotificationPresentationOptionNone, so iOS drops the notification, including a local one from flutter_local_notifications. show() still returns successfully.

    The fix is in #18701. It leaves that handler alone unless this plugin replaced the delegate, owns the notification center, or the notification is a remote FCM message the app asked to present.

    I'll close this in favor of #18699. Your no-credentials repro is a useful extra case — please comment there if that branch still drops the banner.

    dependency_overrides:
      firebase_messaging:
        git:
          url: https://github.com/firebase/flutterfire.git
          ref: messaging_18699
          path: packages/firebase_messaging/firebase_messaging
  3. added and removed
    Needs AttentionThis issue needs maintainer attention.
    on Sep 24, 2026
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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions