Skip to content

FCM error codes, and what to do about each

Every FCM HTTP v1 error code: UNREGISTERED, INVALID_ARGUMENT, SENDER_ID_MISMATCH, QUOTA_EXCEEDED and more, with the Admin SDK codes and when to retry.

PushBy Rushi Patel, Senior iOS developerUpdated 28 October 20267 min read

Every failed FCM HTTP v1 send returns an HTTP status, a status word, and usually an errorCode inside details. The errorCode is the one to act on. This page lists each one, what causes it, whether to retry, and the matching Firebase Admin SDK code, from Google’s own reference.

{
  "error": {
    "code": 404,
    "message": "Requested entity was not found.",
    "status": "NOT_FOUND",
    "details": [
      { "@type": "type.googleapis.com/google.firebase.fcm.v1.FcmError", "errorCode": "UNREGISTERED" }
    ]
  }
}

Every FCM v1 error code

errorCode HTTP What it means What to do Retry
UNREGISTERED 404 The token is dead: app uninstalled, data cleared, app unregistered, or the token refreshed Delete the token. Never send to it again No
INVALID_ARGUMENT 400 The request is malformed: a bad token, a non-string data value, a reserved key, a payload over the limit, a bad TTL Read message and the fieldViolations in details; fix the field it names No
SENDER_ID_MISMATCH 403 The token belongs to another Firebase project than your service account Send with the project the app registered under No
QUOTA_EXCEEDED 429 Too many messages: for the project, for one device or for one topic Slow down; back off from at least 1 minute Yes, with backoff
UNAVAILABLE 503 FCM is overloaded and could not answer in time Back off exponentially, honour Retry-After, add jitter Yes, with backoff
INTERNAL 500 An unknown error inside FCM Retry as for UNAVAILABLE; contact Firebase support if it lasts Yes, with backoff
THIRD_PARTY_AUTH_ERROR 401 The APNs key or certificate, or the web push key, is invalid or missing Upload a valid APNs .p8 key in the Firebase project; check Key ID and Team ID No
UNSPECIFIED_ERROR varies No more information Log the full response and look at message No

INVALID_ARGUMENT: the five usual causes

The same 400 covers several mistakes. The message says which one:

  • “The registration token is not a valid FCM registration token”. The token was cut short, has extra characters (quotes, a newline), or is an APNs device token sent to FCM. Store the token exactly as the app received it from getToken().
  • “Invalid value at ‘message.data[0].value’ (TYPE_STRING)”. Every value in data must be a string. {"order_id": 88213} fails; {"order_id": "88213"} works.
  • Message too big. The payload can be at most 4,096 bytes, or 2,048 bytes for messages to a topic, counting keys and values.
  • A reserved key in data. from, gcm, and anything starting with google are used by FCM itself and are refused.
  • A bad TTL. android.ttl is a duration in seconds as a string ending in s, like "3600s", from 0 to 2,419,200 (4 weeks).

Errors from Google before FCM

Some failures come from Google’s front door, before FCM reads the message. They have a status but no FCM errorCode:

status HTTP Usual cause
UNAUTHENTICATED 401 The OAuth access token is missing, malformed or expired. Tokens from a service account last one hour; make a new one
PERMISSION_DENIED 403 The Firebase Cloud Messaging API is not enabled in the Google Cloud project, or the service account is from another project or lacks permission to send
NOT_FOUND 404 With UNREGISTERED in details: a dead token. Without it: a wrong project id in the URL

The URL must carry the project id, not the project number or name: https://fcm.googleapis.com/v1/projects/YOUR_PROJECT_ID/messages:send.

Firebase Admin SDK error codes

The Admin SDKs for Node, Java, Python and Go turn the same answers into their own codes. The ones you will meet:

Admin SDK code Same as What to do
messaging/registration-token-not-registered UNREGISTERED Delete the token
messaging/invalid-registration-token INVALID_ARGUMENT (token) Check how the token is stored; do not trim or add characters
messaging/invalid-argument INVALID_ARGUMENT Read the message
messaging/invalid-data-payload-key INVALID_ARGUMENT (reserved key) Rename the key
messaging/payload-size-limit-exceeded INVALID_ARGUMENT (size) Make the payload smaller than 4,096 bytes (2,048 to a topic)
messaging/mismatched-credential SENDER_ID_MISMATCH Use the service account of the app’s Firebase project
messaging/message-rate-exceeded, device-message-rate-exceeded, topics-message-rate-exceeded QUOTA_EXCEEDED Send less to that target; do not retry at once
messaging/invalid-apns-credentials THIRD_PARTY_AUTH_ERROR Upload a valid APNs key or certificate
messaging/authentication-error UNAUTHENTICATED Check the credential the SDK starts with
messaging/server-unavailable UNAVAILABLE Retry with backoff
messaging/internal-error INTERNAL Retry with backoff
messaging/too-many-topics The token is already in the maximum number of topics

With sendEachForMulticast the call itself succeeds and each token gets its own result. Check response.responses[i].error?.code for every token, not only failureCount:

const res = await getMessaging().sendEachForMulticast({ tokens, notification: { title, body } });
const dead = [];
res.responses.forEach((r, i) => {
  const code = r.error?.code;
  if (code === "messaging/registration-token-not-registered" || code === "messaging/invalid-registration-token") dead.push(tokens[i]);
});
await db.tokens.deleteMany({ token: { $in: dead } }); // your own store

A retry rule that holds up

  1. 2xx: done.
  2. 404 UNREGISTERED, 400 with an invalid token, 403 SENDER_ID_MISMATCH: the token will never work. Remove it.
  3. Any other 400 or 401: your request or credentials are wrong. Retrying sends the same mistake; log it and fix it.
  4. 429, 500, 503: wait and retry. Start at the Retry-After value if there is one, else 1 second (1 minute for QUOTA_EXCEEDED), double each time, add a little randomness, and give up after a few tries.

Senders that retry hard without backoff can be blocked by Google, so step 4 matters at scale.

When the send succeeds and nothing shows

A 200 with a message name only means FCM accepted the message. If the phone stays silent, the problem is on the device: a data-only message to a closed app, a missing notification permission, Doze, or a phone maker’s battery saver. See FCM says success but the notification never arrives and push on Xiaomi, Oppo, Vivo and Realme.

What SignOps does with these

SignOps Push sends through FCM HTTP v1 with your own service account and reads each answer the same way:

  • UNREGISTERED, SENDER_ID_MISMATCH and an invalid-token INVALID_ARGUMENT remove the device and post device.removed to your webhook.
  • 429 and 5xx answers are retried.
  • Anything else is recorded as the push’s failure reason, which the dashboard shows under See what Google said.

For the iOS side, see APNs error codes.

Sources: Firebase: FCM error codes, Firebase: ErrorCode reference for HTTP v1, Firebase: FCM throttling and quotas.

Frequently asked questions

More questions? Email us and the answer goes on this page.

hello@signops.dev
What does FCM error UNREGISTERED mean?

The token is no longer valid. The app was uninstalled, its data was cleared, it unregistered itself, or Google refreshed the token. It comes back as HTTP 404 with errorCode UNREGISTERED. Delete the token from your database and stop sending to it; the app will register a new one when it next runs.

Why does FCM return SENDER_ID_MISMATCH?

The token was made for a different Firebase project from the one your service account belongs to. A token is tied to the sender that registered it. Use the service account of the project in the app's google-services.json or GoogleService-Info.plist, or register a new token under the project you send from.

Should I retry FCM errors?

Retry only QUOTA_EXCEEDED (429), UNAVAILABLE (503) and INTERNAL (500), with exponential backoff, honouring Retry-After when it is present. For QUOTA_EXCEEDED Google asks for a first delay of at least one minute. Do not retry UNREGISTERED, SENDER_ID_MISMATCH, INVALID_ARGUMENT or THIRD_PARTY_AUTH_ERROR; fix the token, payload or credentials first.

What is the difference between INVALID_ARGUMENT and UNREGISTERED?

INVALID_ARGUMENT (400) means FCM could not accept the request as sent, such as a malformed token, a number inside data, a payload over 4096 bytes or a bad TTL. UNREGISTERED (404) means the request was fine but the token belongs to no app install any more.

What does THIRD_PARTY_AUTH_ERROR mean in FCM?

FCM could not deliver to an iOS device or a web push subscription because the APNs key or certificate in your Firebase project, or the web push key, is invalid or missing. Upload a valid APNs .p8 key under Project settings, Cloud Messaging, and check the Key ID and Team ID.

Send your first push today.

Free for 1,000 push devices, 100 approvals and 1,000 passkey sign-ins a month, and 500 email codes to try. No card until you pass a free amount.