Why your push notification didn't arrive: the FCM and APNs errors, and the failures nobody reports
A push notification has two lives. In the first, your server asks Firebase Cloud Messaging (FCM) or Apple's APNs to deliver it, and gets an answer. In the second, a phone somewhere decides whether to show it. Most debugging goes wrong because people read the first answer as if it described the second. This is a guide to both: what the errors from FCM (HTTP v1) and APNs mean, which ones to retry,…
Push notifications have two stages. The first stage involves your server sending a request to Firebase Cloud Messaging (FCM) or Apple's APNs to deliver the notification. The second stage occurs when the user's phone decides whether to display the message. Many debugging issues arise because people interpret the first response as reflecting the second.
This guide explains the errors from FCM (HTTP v1) and APNs, which ones to retry, which to delete the token, and the failures that provide no error information at all. Accepted does not mean delivered. When APNs returns a 200 status, it merely accepted your request. When FCM responds with a message name, it also signifies acceptance.
Web push services returning a 201 Created status perform the same action according to RFC 8030: the message was accepted. Apple does not provide a signal that the notification was shown. FCM's delivery reports differ from APNs' in that FCM reports are based on Google Analytics and can lag up to 24 hours. To effectively manage this in your system, record the 'accepted by provider' and 'delivered/opened' events as separate facts.
The provider's error categorization helps prioritize actions. Every error is grouped into one of four categories: dead token, incorrect request, wrong setup, or provider issues. Dead tokens should be deleted immediately, while incorrect requests require fixing and retrying. Wrong setup issues involve credentials or configuration errors.
Provider issues include server struggles or excessive requests, which should be retried later using exponential backoff and jitter. Recognizing the distinct error types prevents common mistakes like deleting healthy tokens due to an outage or endlessly retrying dead tokens. FCM (HTTP v1) returns specific error codes that provide valuable insights.
An UNREGISTERED error (404) indicates the token is no longer valid. INVALID_ARGUMENT (400) suggests a parameter issue, such as a malformed token or an overly large message. SENDER_ID_MISMATCH (403) arises when the authentication sender does not match the token's registered sender. QUOTA_EXCEEDED (429) occurs when rate limits are surpassed.
UNAVAILABLE (503) signals FCM overload. INTERNAL (500) denotes an unknown FCM error. APNs categorizes errors differently. A 400 BadDeviceToken indicates an invalid or mismatched token. DeviceTokenNotForTopic (400) means the token doesn't align with the intended topic. ExpiredProviderToken (403) arises when the JWT is stale. InvalidProviderToken (403) suggests an invalid or unverified key.
Unregistered (410) implies the token is no longer active for the topic. PayloadTooLarge (413) indicates the message exceeds the allowed size. TooManyRequests (429) and TooManyProviderTokenUpdates (429) involve retrying with delays. Apple also advises against retrying certain errors to prevent throttling and throttling issues. Mapping each error code to a specific action within your system, logging raw error codes alongside the categorized response, and adhering to the provided guidelines ensures efficient error handling.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.