Centre d'aide Push notifications: troubleshooting and pitfalls

Push notifications: troubleshooting and pitfalls

Push notifications: troubleshooting and pitfalls

A push integration spans four independent systems: your mobile app, the Firebase Console, FCM/APNs, and the SMSBAT backend. Most trouble comes from the fact that when one of them breaks, it usually fails silently or returns a misleading error.

This page collects the traps worth knowing in advance and a procedure for diagnosing a live failure.


1. Three identifiers people mix up

IdentifierWhat it looks likeWhat it is for
Firebase Installation ID (FID)fA9kQ2xRTb2mLp0WYs4nEvIdentifies an installation. Upsert key. Not a send target.
FCM registration tokenfA9kQ2xRTb2mLp0WYs4nEv:APA91b… (~163 chars)The only value message.token accepts for delivery.
Expo push tokenExponentPushToken[...]Expo’s own token. Not used by the SMSBAT Push API.

The FCM token starts with the FID

That shared prefix is exactly why the two get swapped in code. If a value is about 22 characters long, it is a FID; a registration token is far longer and contains a colon.


2. Seven integration traps

1. RNFirebase v26 removed the messaging() call

In @react-native-firebase/messaging v26+ the old namespaced syntax returns undefined.

  • Symptom: Object is not a function when requesting a token.

  • Fix: use the modular API only:

    import { getMessaging, getToken, getAPNSToken } from '@react-native-firebase/messaging';
    
    const msgInstance = getMessaging();
    const fcmToken = await getToken(msgInstance);
    

2. One try/catch around both the FID and the token

If you fetch the FID and the FCM token in the same try block and getToken() throws — which it often does on iOS before permission is granted — you lose both.

  • Fix: fetch them in separate try/catch blocks. A missing token must not block registerInstallation.

3. The APNs token arrives late on iOS

registerDeviceForRemoteMessages() resolves as soon as the request is made. The APNs token itself comes back from Apple later.

  • Fix: poll getAPNSToken() (10 attempts, 500 ms apart) before calling getToken().

4. Two push services competing on Android

If the app contains both expo-notifications and @react-native-firebase/messaging, two FirebaseMessagingService entries end up registered in AndroidManifest.xml.

  • Symptom: Android hands the push to one of them only. If RNFirebase wins while your listener sits in Expo, no banner appears and no delivered callback is sent.
  • Fix: subscribe at both levels and de-duplicate on data.guid.

5. Data-only messages are not drawn by the system

SMSBAT sends data-only messages so the app can report delivered before the user opens anything.

  • Symptom: no system banner appears, even though the push arrived.
  • Fix: the app must draw the local notification itself, in both background and foreground.

6. Sending a FID where a token is expected

Send test message in the Firebase Console accepts a FID because it converts it internally. The REST API v1 does not — it requires an FCM registration token.

  • Symptom: 404 UNREGISTERED for a bare FID in the token field.

7. Token rotation

Reinstalling the app or clearing its data produces a new FID and token.

  • Fix: upsert on externalUserId + platform, and deactivate the stale installation as soon as FCM answers UNREGISTERED.

3. Diagnosing a live failure

When push does not arrive, or the cascade does not stop, walk the chain in order — each step tells you which of the four systems to blame.

  1. Is there a token on the device? Show it on a diagnostics screen in the app. Empty means the problem is in the mobile code or in the OS permission, and nothing further down matters yet.
  2. Does a direct cURL request to FCM V1 arrive? If it does, the app and the Firebase keys are fine and the problem is on the sending side.
  3. Do you see SenderIdMismatch? The google-services.json in the app belongs to a different Firebase project than the service account JSON in SMSBAT.
  4. Do you see ThirdPartyAuthError? The Firebase service account expired or was revoked. Upload a fresh JSON in the Omni panel and press the refresh button on the integration.

Build the diagnostics screen first

A screen showing the FID, the FCM token, the APNs token, the permission state and the last registration response answers step 1 in seconds. Without it, every report becomes guesswork.