<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[notifySphere Guides]]></title><description><![CDATA[notifySphere Guides]]></description><link>https://notifysphere.hashnode.dev</link><image><url>https://cdn.hashnode.com/uploads/logos/6aec8c0ae4ee234ef660c077/a620a388-cfad-47a0-bcb9-6f84394d50fa.png</url><title>notifySphere Guides</title><link>https://notifysphere.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Sat, 07 Nov 2026 13:53:39 GMT</lastBuildDate><atom:link href="https://notifysphere.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[FCM UNREGISTERED Error: Requested Entity Was Not Found, and How to Fix It]]></title><description><![CDATA[FCM 404 UNREGISTERED means the device token no longer works. Why it happens, how to clean up tokens, and when it's a different error.]]></description><link>https://notifysphere.hashnode.dev/fcm-unregistered-error-requested-entity-was-not-found-and-how-to-fix-it</link><guid isPermaLink="true">https://notifysphere.hashnode.dev/fcm-unregistered-error-requested-entity-was-not-found-and-how-to-fix-it</guid><category><![CDATA[Firebase]]></category><category><![CDATA[push notifications]]></category><category><![CDATA[Android]]></category><dc:creator><![CDATA[Sandeep Joshi]]></dc:creator><pubDate>Sat, 07 Nov 2026 05:26:34 GMT</pubDate><content:encoded><![CDATA[<p>Your push send returns <code>404 UNREGISTERED</code>, “Requested entity was not found” or <code>messaging/registration-token-not-registered</code>. The message didn't fail because of your payload: FCM is telling you that device token no longer works. The fix is to delete it, and to stop dead tokens building up.</p>
<h2>What the error looks like</h2>
<p>This is the response from the FCM HTTP v1 API:</p>
<pre><code class="language-json">{
  "error": {
    "code": 404,
    "message": "Requested entity was not found.",
    "status": "NOT_FOUND",
    "details": [
      {
        "@type": "type.googleapis.com/google.firebase.fcm.v1.FcmError",
        "errorCode": "UNREGISTERED"
      }
    ]
  }
}
</code></pre>
<p>The Firebase Admin SDK for Node.js reports the same thing as <code>messaging/registration-token-not-registered</code>. Other SDKs have their own names for it, so check the <code>errorCode</code> or the SDK's docs rather than matching the message text.</p>
<h2>Why a token stops working</h2>
<ul>
<li><strong>The app was uninstalled</strong>, or the token was invalidated on the device.</li>
<li><strong>The token was replaced.</strong> Tokens can change, for example after a reinstall or when your app calls <code>deleteToken()</code>, and your server may still hold the old one.</li>
<li><strong>The token expired.</strong> On Android, Firebase treats a registration as expired after 270 days of inactivity.</li>
<li><strong>APNs rejected the token on iOS.</strong> Firebase relies on APNs there, so an invalid APNs token can surface as the same error.</li>
<li><strong>The token string was changed.</strong> A token that was cut short or altered when stored can fail, so save it exactly as you received it.</li>
</ul>
<h2>How to fix it</h2>
<ol>
<li><strong>Delete the token when FCM says it's dead.</strong> Check each result in a batch, because one bad token doesn't fail the others.</li>
<li><strong>Don't retry it.</strong> Retries only waste sends. Save retries for temporary errors.</li>
<li><strong>Send the new token to your server.</strong> Upload it on app start and whenever it refreshes.</li>
<li><strong>Store a timestamp with each token,</strong> and update it on every upload, so you can see which ones are stale.</li>
<li><strong>Remove stale tokens on a schedule.</strong> Firebase's default definition of stale is more than a month without connecting to FCM, and it suggests refreshing tokens about once a month. Choose a window that suits your app.</li>
</ol>
<p>Here's step 1 with the Firebase Admin SDK for Node.js:</p>
<pre><code class="language-javascript">import { getMessaging } from "firebase-admin/messaging";

const TOKEN_IS_DEAD = "messaging/registration-token-not-registered";

export async function sendToTokens(tokens, notification) {
  const result = await getMessaging().sendEachForMulticast({ tokens, notification });

  const deadTokens = [];
  result.responses.forEach((response, i) =&gt; {
    if (!response.success &amp;&amp; response.error?.code === TOKEN_IS_DEAD) {
      deadTokens.push(tokens[i]);
    }
  });

  // Your own function: delete these tokens from your database
  await removeTokens(deadTokens);
}
</code></pre>
<h2>When it's a different FCM error</h2>
<p>Only delete tokens for the errors that call for it. These need a different fix:</p>
<table>
<thead>
<tr>
<th>Error</th>
<th>HTTP</th>
<th>What it means</th>
<th>What to do</th>
</tr>
</thead>
<tbody><tr>
<td><code>UNREGISTERED</code></td>
<td>404</td>
<td>The token is usually no longer valid</td>
<td>Delete the token</td>
</tr>
<tr>
<td><code>INVALID_ARGUMENT</code></td>
<td>400</td>
<td>A request value is invalid, which may be the payload or the token</td>
<td>Check the payload first. Delete the token only if the payload is completely valid</td>
</tr>
<tr>
<td><a href="https://notifysphere.net/blog/fcm-sender-id-mismatch"><code>SENDER_ID_MISMATCH</code></a></td>
<td>403</td>
<td>The token belongs to a different sender</td>
<td>Send from the Firebase project the app registered with</td>
</tr>
<tr>
<td><code>THIRD_PARTY_AUTH_ERROR</code></td>
<td>401</td>
<td>The APNs certificate or web push key is invalid or missing</td>
<td>Check your credentials. Don't delete tokens</td>
</tr>
<tr>
<td><code>QUOTA_EXCEEDED</code></td>
<td>429</td>
<td>A sending limit was exceeded</td>
<td>Slow down and retry with backoff</td>
</tr>
<tr>
<td><code>UNAVAILABLE</code>, <code>INTERNAL</code></td>
<td>503, 500</td>
<td>A temporary problem at FCM</td>
<td>Retry with backoff and check the FCM status dashboard</td>
</tr>
</tbody></table>
<p>You can build a valid test message with the free <a href="https://notifysphere.net/tools/fcm-payload-builder">FCM payload builder</a>, which helps rule out the payload.</p>
<h2>If almost every token fails at once</h2>
<p>A few dead tokens are normal, because people uninstall apps. If most of your tokens suddenly fail, look for a shared cause before you delete anything:</p>
<ul>
<li>Did you change Firebase projects or service accounts recently?</li>
<li>Did your code start altering tokens when it stores or reads them?</li>
<li>Can you get a fresh token from a test device and send to it?</li>
<li>Does the FCM status dashboard show a problem?</li>
</ul>
<p>Pause any automatic cleanup while you check, so a bug on your side doesn't wipe good tokens. If a fresh token also fails and your setup looks right, contact Firebase support.</p>
<h2>On notifySphere</h2>
<p>The notifySphere <a href="https://notifysphere.net/blog/react-native-push-notifications">React Native SDK</a> re-registers a device when its FCM token changes, and <code>logout()</code> unsubscribes the device and deletes its token when someone signs out. For the iOS setup error that often comes before this one, see <a href="https://notifysphere.net/blog/no-apns-token-specified-before-fetching-fcm-token">No APNS token specified before fetching FCM token</a>.</p>
<h2>Frequently asked questions</h2>
<h3>What does FCM UNREGISTERED mean?</h3>
<p>It means the app instance is no longer registered with Firebase Cloud Messaging, so that token usually won't work again. Firebase's advice is to remove the token and stop sending to it. The app gets a new token the next time it registers.</p>
<h3>Is registration-token-not-registered the same as UNREGISTERED?</h3>
<p>Yes, for practical purposes. UNREGISTERED is the error code from the FCM HTTP v1 API, usually with a 404 and the message "Requested entity was not found." messaging/registration-token-not-registered is how the Firebase Admin SDK for Node.js reports it.</p>
<h3>Should I retry a message that failed with UNREGISTERED?</h3>
<p>No. Retrying won't bring the token back. Retry 429, 500 and 503 errors with backoff instead, and delete tokens that return UNREGISTERED.</p>
<h3>Do FCM tokens expire?</h3>
<p>On Android, Firebase treats a registration as expired after 270 days of inactivity. On iOS and other platforms it relies on the underlying push service, which doesn't have that limit, so Firebase recommends removing stale tokens yourself. Its default definition of stale is no connection to FCM for over a month.</p>
<h3>Does UNREGISTERED mean the user uninstalled the app?</h3>
<p>Often, but not always. It can also follow an app update, a token refresh, or your app deleting its token. Treat it as a dead token, not as proof of an uninstall, especially if you use it to measure uninstalls.</p>
<hr />
<p><em>Originally published on the <a href="https://notifysphere.net/blog/fcm-unregistered-token">notifySphere blog</a>. notifySphere is push notifications, WhatsApp Business API, deep linking, and in-app support in one SDK — <a href="https://notifysphere.net/pricing">free up to 1,000 users</a>.</em></p>
]]></content:encoded></item><item><title><![CDATA[FCM SENDER_ID_MISMATCH (403) and messaging/mismatched-credential: How to Fix It]]></title><description><![CDATA[FCM 403 SENDER_ID_MISMATCH means your server sends from a different Firebase project than the app's token. How to find and fix it.]]></description><link>https://notifysphere.hashnode.dev/fcm-sender-id-mismatch-403-and-messaging-mismatched-credential-how-to-fix-it</link><guid isPermaLink="true">https://notifysphere.hashnode.dev/fcm-sender-id-mismatch-403-and-messaging-mismatched-credential-how-to-fix-it</guid><category><![CDATA[Firebase]]></category><category><![CDATA[push notifications]]></category><category><![CDATA[Android]]></category><dc:creator><![CDATA[Sandeep Joshi]]></dc:creator><pubDate>Sat, 07 Nov 2026 05:23:13 GMT</pubDate><content:encoded><![CDATA[<p>Your push send fails with <code>403 SENDER_ID_MISMATCH</code>, or the Node.js Admin SDK throws <code>messaging/mismatched-credential</code>. The token isn't dead. Your server is sending from a different Firebase project than the one the app registered with.</p>
<h2>What the error looks like</h2>
<p>The FCM HTTP v1 API returns a 403 with the error code in the details:</p>
<pre><code class="language-json">{
  "error": {
    "code": 403,
    "status": "PERMISSION_DENIED",
    "details": [
      {
        "@type": "type.googleapis.com/google.firebase.fcm.v1.FcmError",
        "errorCode": "SENDER_ID_MISMATCH"
      }
    ]
  }
}
</code></pre>
<p>Firebase's description: the authenticated sender ID is different from the sender ID for the registration token. A token is tied to the senders of the project the app used when it registered, and only those senders can use it.</p>
<h2>Common causes</h2>
<ul>
<li><strong>Dev and production projects are mixed up.</strong> The app was built with the dev <code>google-services.json</code> or <code>GoogleService-Info.plist</code>, while the server uses the production service account, or the other way round. Build flavors and schemes make this easy to miss.</li>
<li><strong>You moved to a new Firebase project.</strong> Old installs still hold tokens from the old project.</li>
<li><strong>The server uses the wrong key file.</strong> A service account key from another project, or a project ID in the send URL that doesn't match the key.</li>
<li><strong>Several apps share one server.</strong> Tokens from apps in different projects are stored together and sent with one set of credentials.</li>
</ul>
<h2>How to find the mismatch</h2>
<p>Compare the project the app uses with the project the server uses:</p>
<pre><code># Android app: the sender ID is the project number
google-services.json  -&gt;  project_info.project_number
                          project_info.project_id

# iOS app
GoogleService-Info.plist  -&gt;  GCM_SENDER_ID
                              PROJECT_ID

# Your server: the project in the service account key and the send URL
service-account.json  -&gt;  project_id
POST https://fcm.googleapis.com/v1/projects/&lt;project_id&gt;/messages:send
</code></pre>
<ol>
<li>Open the config file that is actually bundled in the build that produced the token.</li>
<li>Note its project ID and sender ID (on Android the sender ID is the <code>project_number</code>).</li>
<li>Check the <code>project_id</code> in the server's service account key and in the send URL.</li>
<li>They must all point to the same Firebase project.</li>
</ol>
<p>A quick test: install a fresh build on a test phone, copy its token, and send to it from the project in that build's config file. If that works, the setup is fine and the failing tokens belong to another project.</p>
<h2>How to fix it</h2>
<ol>
<li><strong>Send with the matching project.</strong> Use the service account and project ID that match the app's config file.</li>
<li><strong>Store the project with each token.</strong> If you run several apps or environments, save which project a token came from and choose credentials per send.</li>
<li><strong>After a project move, let tokens refresh.</strong> Ship the build with the new config, upload the new token on app start, and keep sending to old tokens from the old project until users update.</li>
<li><strong>Don't bulk-delete tokens on this error.</strong> Firebase's clean-up advice is for <a href="https://notifysphere.net/blog/fcm-unregistered-token">UNREGISTERED</a> and, when the payload is valid, <code>INVALID_ARGUMENT</code>. Deleting on a mismatch can wipe tokens that work fine with the right project.</li>
</ol>
<p>You can build a valid test message with the free <a href="https://notifysphere.net/tools/fcm-payload-builder">FCM payload builder</a>, so the payload isn't in question while you test.</p>
<h2>Related errors</h2>
<ul>
<li><code>UNREGISTERED</code> (404): the token is no longer valid. Delete it. See <a href="https://notifysphere.net/blog/fcm-unregistered-token">FCM UNREGISTERED: Requested entity was not found</a>.</li>
<li><code>THIRD_PARTY_AUTH_ERROR</code> (401): the APNs key or certificate in Firebase is missing or invalid.</li>
<li>On iOS, if you send to APNs directly, a token sent to the wrong environment returns <a href="https://notifysphere.net/blog/apns-bad-device-token">BadDeviceToken</a>.</li>
</ul>
<h2>On notifySphere</h2>
<p>notifySphere sends through FCM with the <a href="https://notifysphere.net/docs/firebase-credentials">Firebase credentials you add for each app</a>, so each app's devices are sent with that app's project. The <a href="https://notifysphere.net/blog/react-native-push-notifications">React Native</a> and <a href="https://notifysphere.net/blog/flutter-push-notifications">Flutter</a> SDKs register the device for you.</p>
<h2>Frequently asked questions</h2>
<h3>What does FCM SENDER_ID_MISMATCH mean?</h3>
<p>Firebase describes it as: the authenticated sender ID is different from the sender ID for the registration token. In practice, the token was created by an app connected to one Firebase project, and your server is sending with credentials from another project.</p>
<h3>Is messaging/mismatched-credential the same error?</h3>
<p>Yes. The Firebase Admin SDK for Node.js reports SENDER_ID_MISMATCH as messaging/mismatched-credential, with a message saying the credential doesn't have permission to send to that token.</p>
<h3>Should I delete tokens that return SENDER_ID_MISMATCH?</h3>
<p>Not as a first step. Firebase's token clean-up advice covers UNREGISTERED and, with a valid payload, INVALID_ARGUMENT. A mismatch usually means your server is using the wrong project, so the tokens may be fine for the right one. Fix the credentials, then retry.</p>
<h3>Why did SENDER_ID_MISMATCH start after I moved to a new Firebase project?</h3>
<p>Tokens are tied to the project the app registered with. Existing installs keep their old tokens until they run a build connected to the new project and register again. Until then, sending to those tokens from the new project fails with SENDER_ID_MISMATCH.</p>
<h3>Can one server send to apps in two Firebase projects?</h3>
<p>Yes, but each send must use credentials and a project ID that match the token's project. Keep the project with each stored token and pick the matching credentials when you send. Firebase also documents authorizing a service account from a different project.</p>
<hr />
<p><em>Originally published on the <a href="https://notifysphere.net/blog/fcm-sender-id-mismatch">notifySphere blog</a>. notifySphere is push notifications, WhatsApp Business API, deep linking, and in-app support in one SDK — <a href="https://notifysphere.net/pricing">free up to 1,000 users</a>.</em></p>
]]></content:encoded></item><item><title><![CDATA[Fix “No APNS token specified before fetching FCM Token” on iOS (React Native & Flutter)]]></title><description><![CDATA[What the FCM error means on iOS and how to fix it in React Native, Flutter and Swift: capabilities, call order and swizzling.]]></description><link>https://notifysphere.hashnode.dev/fix-no-apns-token-specified-before-fetching-fcm-token-on-ios-react-native-flutter</link><guid isPermaLink="true">https://notifysphere.hashnode.dev/fix-no-apns-token-specified-before-fetching-fcm-token-on-ios-react-native-flutter</guid><category><![CDATA[Firebase]]></category><category><![CDATA[iOS]]></category><category><![CDATA[React Native]]></category><category><![CDATA[Flutter]]></category><dc:creator><![CDATA[Sandeep Joshi]]></dc:creator><pubDate>Thu, 05 Nov 2026 14:21:40 GMT</pubDate><content:encoded><![CDATA[<p>You set up Firebase Cloud Messaging, it works on Android, and on iOS the app throws <code>No APNS token specified before fetching FCM Token</code>. Here's what the error actually means and how to fix it in React Native, Flutter and native Swift.</p>
<h2>What the error means</h2>
<p>On iOS, getting a push token is a two-step handoff:</p>
<ol>
<li>Your app registers with Apple Push Notification service (APNs), and iOS gives it an APNs token.</li>
<li>Firebase exchanges that APNs token for an FCM token, which your server uses to send pushes.</li>
</ol>
<p>If your code calls <code>getToken()</code> 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:</p>
<pre><code class="language-text">// 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 '…'
</code></pre>
<h2>Quick checklist</h2>
<ul>
<li><strong>Push Notifications capability</strong> is added in Xcode under Signing &amp; Capabilities.</li>
<li><strong>Background Modes → Remote notifications</strong> is enabled.</li>
<li>You're testing on a <strong>real iPhone</strong>, not the simulator.</li>
<li>The app <strong>registers for remote notifications before</strong> calling <code>getToken()</code>.</li>
<li>If method swizzling is off, the AppDelegate <strong>passes the APNs token to Firebase</strong>.</li>
</ul>
<h2>1. Add the Push Notifications capability</h2>
<p>Open <code>ios/YourApp.xcworkspace</code> in Xcode, select your app target, go to <strong>Signing &amp; Capabilities</strong> and add <strong>Push Notifications</strong> and <strong>Background Modes</strong> (tick <em>Remote notifications</em>). This adds the <code>aps-environment</code> 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.</p>
<h2>2. Fix the call order in React Native</h2>
<p>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:</p>
<pre><code class="language-javascript">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();
}
</code></pre>
<p>If you set <code>messaging_ios_auto_register_for_remote_messages</code> to <code>false</code> in <code>firebase.json</code>, the <code>registerDeviceForRemoteMessages()</code> call above is required.</p>
<h2>3. Wait for the APNs token in Flutter</h2>
<p>In Flutter, <code>getToken()</code> fails with <code>apns-token-not-set</code> when the APNs token hasn't arrived yet. Check <code>getAPNSToken()</code> first and give it a moment on first launch:</p>
<pre><code class="language-dart">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 &amp;&amp; i &lt; 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
}
</code></pre>
<p>Also listen to <code>FirebaseMessaging.instance.onTokenRefresh</code>, so you still capture the token if it arrives after your retries.</p>
<h2>4. Pass the token yourself if swizzling is disabled</h2>
<p>Firebase normally intercepts the APNs token through method swizzling. If your <code>Info.plist</code> sets <code>FirebaseAppDelegateProxyEnabled</code> to <code>NO</code>, which some apps do to avoid conflicts with other SDKs, you have to hand the token over manually:</p>
<pre><code class="language-swift">// 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)")
}
</code></pre>
<p>The failure callback is worth adding either way. If registration fails, it tells you why, usually a missing entitlement.</p>
<h2>5. Test on a real device</h2>
<p>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.</p>
<h2>Skip the token plumbing</h2>
<p>The <a href="https://notifysphere.net/blog/react-native-push-notifications">notifySphere React Native SDK</a> 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 <a href="https://notifysphere.net/blog/firebase-ios-push-notifications">Firebase iOS push guide</a> for the APNs key and capabilities, or the <a href="https://notifysphere.net/blog/flutter-push-notifications">Flutter push guide</a>.</p>
<h2>Frequently asked questions</h2>
<h3>What does “No APNS token specified before fetching FCM Token” mean?</h3>
<p>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.</p>
<h3>Does this error happen on Android?</h3>
<p>No. Android doesn't use APNs, so FCM tokens are issued directly. The error is specific to iOS (and macOS) apps using Firebase Messaging.</p>
<h3>Can I get an APNs token on the iOS Simulator?</h3>
<p>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.</p>
<h3>I uploaded my APNs key to Firebase. Why do I still get this error?</h3>
<p>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.</p>
<h3>How do I know if APNs registration failed?</h3>
<p>Implement <code>application(_:didFailToRegisterForRemoteNotificationsWithError:)</code> 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.</p>
<hr />
<p><em>Originally published on the <a href="https://notifysphere.net/blog/no-apns-token-specified-before-fetching-fcm-token">notifySphere blog</a>. notifySphere is push notifications, WhatsApp Business API, deep linking, and in-app support in one SDK — <a href="https://notifysphere.net/pricing">free up to 1,000 users</a>.</em></p>
]]></content:encoded></item></channel></rss>