Push troubleshooting

Diagnose common Android push notification issues and understand FCM error codes.

This guide walks through the most common reasons notifications fail to arrive, delivery tracking gaps, build-time errors, and the FCM error codes you may encounter in server responses.

On this page

Nothing arrives on device

Work through this checklist in order:

  1. google-services.json — confirm the file is in the app/ module root and matches the Firebase project you are using. The project_number in the file must match the Sender ID configured in ZMP.
  2. Firebase Messaging dependency — confirm com.google.firebase:firebase-messaging is declared in your app/build.gradle. Without it, the device never registers for push.
  3. Google Play Services — FCM requires Google Play Services on the device. Huawei-only devices or emulators without the Google APIs image do not receive FCM messages.
  4. POST_NOTIFICATIONS permission — on Android 13 (API 33) and above, the app must request android.permission.POST_NOTIFICATIONS at runtime before notifications can be displayed. Without it, messages arrive but are not shown to the user.
  5. ZTPushService declared in the manifest — the SDK ships a FirebaseMessagingService implementation (ZTPushService) that should be declared in your AndroidManifest.xml with priority="-1" (the SDK default). If you use a custom FirebaseMessagingService, confirm it forwards every incoming message to ZTPush.handleMessage().
override fun onMessageReceived(remoteMessage: RemoteMessage) {
    ZTPush.handleMessage(this, remoteMessage)
}
@Override
public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {
    ZTPush.INSTANCE.handleMessage(this, remoteMessage);
}

Delivery tracking is not working

If notifications arrive and clicks register, but delivered events are missing in ZMP:

  1. Custom FirebaseMessagingService — if you replaced or overrode the default ZTPushService, confirm every incoming RemoteMessage is forwarded to ZTPush.handleMessage(context, remoteMessage). The SDK records the delivered event inside that call.
  2. Service priority conflict — if your app declares another FirebaseMessagingService with a higher priority than ZTPushService, the other service receives the messages first and ZTPushService is never invoked. Either lower the other service's priority or forward messages manually.
  3. SDK initialization timing — the SDK must be initialized before messages arrive. If ZetaClient.initialize() is called lazily (for example, only after the user logs in), messages that arrive before initialization are not tracked. Initialize the SDK as early as possible, ideally in Application.onCreate().

Build errors

ErrorFix
Duplicate FirebaseMessagingServiceMore than one FirebaseMessagingService is declared without priority disambiguation. Set android:priority="-1" on ZTPushService (SDK default) and a higher priority on your own service, or remove the duplicate.
Missing google-services.jsonDownload from the Firebase console and place it in the app/ module root. The Gradle build fails at configuration time without it.
Missing com.google.gms.google-services pluginAdd id("com.google.gms.google-services") to your app/build.gradle.kts plugins block (or apply plugin: 'com.google.gms.google-services' if using Groovy).

FCM error codes

These errors are returned by Firebase Cloud Messaging when a push send fails. Some are caused by app-side configuration (marked Developer action); others originate at the provider layer (marked Escalate to Zeta).

Source: Firebase: ErrorCode reference and Firebase: Troubleshooting

Token errors

UNREGISTERED / NotRegistered (HTTP 404) — Developer action

The registration token is no longer valid. Common causes:

  • The user uninstalled the app.
  • FCM credentials were rotated on the Firebase project — devices registered with the old credentials hold stale tokens until the app re-registers.
  • A second push service registration (via a different Sender ID) invalidated the token the SDK received.
  • Custom app logic programmatically unregistered the device from push.

This error does not mean the user is push-disabled — only that a specific token was removed. It is common for testers who frequently install and uninstall the app.

InvalidRegistration (HTTP 400) — Developer action

The push token is malformed. Common causes:

  • The app passed an Instance ID or another value instead of the token from FirebaseMessaging.getInstance().token.
  • The app registers with multiple push services, and an intent from a different service produced an invalid token.

INVALID_ARGUMENT (HTTP 400, bad token) — Developer action

The registration token format is invalid, or the request contains other invalid parameters. Verify the token is the full string returned by the FCM SDK.

Authentication errors

MismatchSenderId / SENDER_ID_MISMATCH (HTTP 403) — Escalate to Zeta

The Sender ID used to send the message does not match the one tied to the registration token. This can also occur if the app registers with multiple push services using different Sender IDs.

Resolution: Confirm the Sender ID in your google-services.json matches the one configured in ZMP, then contact your Zeta account team.

THIRD_PARTY_AUTH_ERROR (HTTP 401) — Escalate to Zeta

The FCM server key or service account credentials are invalid or have been revoked. Contact your Zeta account team.

Payload errors

INVALID_ARGUMENT (HTTP 400, payload size) — Developer action

The notification payload exceeds the FCM limit (4 KB for notification messages, 4 KB for data messages). If you use Additional Values in the ZMP campaign builder, large or numerous key-value pairs can push the payload over the limit. Reduce the number or size of Additional Values.

Rate limiting

QUOTA_EXCEEDED (HTTP 429) — Informational

FCM enforces per-device, per-project, and per-topic rate limits. When exceeded, messages are queued and delivered when the quota resets. Common during bulk sends or testing.

The condition is temporary. If sustained, check your sending patterns for unintentional loops.

Server errors

ErrorHTTPDescription
INTERNAL500An unexpected error on Google's side. Transient — retry the send.
UNAVAILABLE503FCM is temporarily unable to process the request. Transient — retry with exponential backoff.

See also