Push

Fix “No APNS token specified before fetching FCM Token” on iOS (React Native & Flutter)

9:41

You set up Firebase Cloud Messaging, it works on Android, and on iOS the app throws No APNS token specified before fetching FCM Token. Here's what the error actually means and how to fix it in React Native, Flutter and native Swift.

What the error means

On iOS, getting a push token is a two-step handoff:

  1. Your app registers with Apple Push Notification service (APNs), and iOS gives it an APNs token.
  2. Firebase exchanges that APNs token for an FCM token, which your server uses to send pushes.

If your code calls getToken() before step 1 has finished, or step 1 fails silently, Firebase has nothing to exchange and throws this error. The exact wording depends on your stack:

// React Native Firebase
[messaging/unknown] No APNS token specified before fetching FCM Token

// Flutter (firebase_messaging)
[firebase_messaging/apns-token-not-set] APNS token has not been set yet.

// Native iOS log
APNS device token not set before retrieving FCM Token for Sender ID '…'

Quick checklist

  • Push Notifications capability is added in Xcode under Signing & Capabilities.
  • Background Modes → Remote notifications is enabled.
  • You're testing on a real iPhone, not the simulator.
  • The app registers for remote notifications before calling getToken().
  • If method swizzling is off, the AppDelegate passes the APNs token to Firebase.

1. Add the Push Notifications capability

Open ios/YourApp.xcworkspace in Xcode, select your app target, go to Signing & Capabilities and add Push Notifications and Background Modes (tick Remote notifications). This adds the aps-environment entitlement. Without it, iOS refuses to issue an APNs token and you get this error every time. If you sign with a manual provisioning profile, regenerate it after enabling push.

2. Fix the call order in React Native

React Native Firebase registers for remote messages automatically by default, but if your code asks for the token very early at launch, it can run before registration completes. Request permission, make sure the device is registered, then fetch the token:

import messaging from "@react-native-firebase/messaging";

export async function getFcmToken() {
  // 1. Ask for permission (shows the iOS prompt)
  await messaging().requestPermission();

  // 2. Make sure the device is registered with APNs first
  if (!messaging().isDeviceRegisteredForRemoteMessages) {
    await messaging().registerDeviceForRemoteMessages();
  }

  // 3. Only now ask Firebase for the FCM token
  return messaging().getToken();
}

If you set messaging_ios_auto_register_for_remote_messages to false in firebase.json, the registerDeviceForRemoteMessages() call above is required.

3. Wait for the APNs token in Flutter

In Flutter, getToken() fails with apns-token-not-set when the APNs token hasn't arrived yet. Check getAPNSToken() first and give it a moment on first launch:

final messaging = FirebaseMessaging.instance;
await messaging.requestPermission();

// The APNs token can arrive a moment after launch, so wait for it
String? apnsToken = await messaging.getAPNSToken();
for (var i = 0; apnsToken == null && i < 5; i++) {
  await Future.delayed(const Duration(seconds: 1));
  apnsToken = await messaging.getAPNSToken();
}

if (apnsToken != null) {
  final fcmToken = await messaging.getToken();
  // send fcmToken to your server
}

Also listen to FirebaseMessaging.instance.onTokenRefresh, so you still capture the token if it arrives after your retries.

4. Pass the token yourself if swizzling is disabled

Firebase normally intercepts the APNs token through method swizzling. If your Info.plist sets FirebaseAppDelegateProxyEnabled to NO, which some apps do to avoid conflicts with other SDKs, you have to hand the token over manually:

// AppDelegate.swift — needed when FirebaseAppDelegateProxyEnabled is NO
func application(_ application: UIApplication,
                 didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
  Messaging.messaging().apnsToken = deviceToken
}

func application(_ application: UIApplication,
                 didFailToRegisterForRemoteNotificationsWithError error: Error) {
  print("APNs registration failed: \(error)")
}

The failure callback is worth adding either way. If registration fails, it tells you why, usually a missing entitlement.

5. Test on a real device

APNs registration on the iOS Simulator is unreliable, even on setups that can display simulated pushes. If the error only appears in the simulator, try a real iPhone before changing any code.

Skip the token plumbing

The notifySphere React Native SDK registers the device with APNs before it requests the FCM token, so this ordering problem doesn't come up. It also tracks delivery and taps for every notification. Setting up the Apple side for the first time? Follow the Firebase iOS push guide for the APNs key and capabilities, or the Flutter push guide.

Frequently asked questions

What does “No APNS token specified before fetching FCM Token” mean?

On iOS, Firebase Cloud Messaging needs the device's APNs token from Apple before it can create an FCM token. The error means your app asked Firebase for the FCM token before iOS had delivered the APNs token, or iOS never delivered one at all.

Does this error happen on Android?

No. Android doesn't use APNs, so FCM tokens are issued directly. The error is specific to iOS (and macOS) apps using Firebase Messaging.

Can I get an APNs token on the iOS Simulator?

Support is limited. Recent Xcode versions on Apple silicon Macs can deliver remote notifications to the simulator, but registration is still unreliable there. Test push notifications on a real iPhone to rule the simulator out.

I uploaded my APNs key to Firebase. Why do I still get this error?

The APNs key in the Firebase console is used when Firebase sends a push to Apple. This error happens earlier, on the device, when the app registers with APNs. Check the Push Notifications capability, the provisioning profile and the order of your calls instead.

How do I know if APNs registration failed?

Implement application(_:didFailToRegisterForRemoteNotificationsWithError:) in your AppDelegate and log the error. The most common message is a missing aps-environment entitlement, which means the Push Notifications capability or provisioning profile is wrong.