# Troubleshooting
# Push notifications not arriving
Check notification permission
The SDK requests permission only when you explicitly call registerForRemoteNotifications. If you haven't called it yet, or the user denied the prompt, no notifications will be delivered.
To verify the current permission status, check in Settings → [Your App] → Notifications on the device.
Check the FCM token
Without a valid FCM token the device can't receive notifications. The token is registered automatically after registerForRemoteNotifications succeeds. You can verify it was received by checking UserSDK.default?.userId - it's populated after the first successful ping(), which the SDK triggers automatically when the token is ready.
Simulators don't support push notifications
Push notifications only work on a physical iOS device. This is an Apple platform limitation - simulators will never receive them. Always test push flows on real hardware.
When to call registerForRemoteNotifications
You don't have to call it at app launch. The prompt can appear at any point in your user's journey - after login, on a settings screen, wherever makes sense for your product. What matters is that you call it before you need to deliver the first notification.
# Firebase & FCM errors
Mismatch Sender ID
This error means the GoogleService-Info.plist in your app doesn't match the Firebase project you uploaded to Positive User. Make sure both point to the same Firebase project.
Steps to check:
- In Firebase Console, go to Project settings → Your apps and confirm the correct iOS app is selected
- Re-download
GoogleService-Info.plistand replace the one in your Xcode project - In Positive User, go to Settings → App Settings → Advanced → Mobile keys and confirm the SDK Admin key was generated from the same Firebase project
Unregistered
The device token was revoked or expired. This typically happens after a reinstall or when the app hasn't been opened in a long time. A new token is registered automatically next time the app calls registerForRemoteNotifications.
FCM token not being passed to Positive User
The SDK sends the FCM token automatically via ping() whenever the token is refreshed. If the token isn't appearing in Positive User, check:
registerForRemoteNotificationshas been calledGoogleService-Info.plistis present and added to the correct targetFirebaseApp.configure()is not being called elsewhere in your app — the SDK handles this internally
# Push notification image not showing
If a push notification arrives without the attached image, work through these checks in order:
Notification Service Extension not set up - images require a Notification Service Extension with
NotificationExtensionHelper. See Push Notifications.HTTP instead of HTTPS - Apple's App Transport Security blocks non-HTTPS image URLs. Make sure the image URL uses
https://.Image too large - iOS imposes a 10 MB limit on notification attachments. If the image exceeds that, the notification appears without it.
Image server not responding - The extension has a short time window to fetch and attach the image. If the server is slow or unreachable, the notification displays without the image. Check that the image URL is publicly accessible.
# Events not being sent
sendEvent or trackScreen returning an error immediately after init
Both methods require a contact to exist - internally they check userId != nil. If you call them before the first ping() has completed and returned a contact ID, they'll fail immediately with a userNotExistsError.
The fix: call ping() first and send events in its completion handler, or wait until you know the contact session is established.
UserSDK.default?.ping { success, _ in
guard success else { return }
UserSDK.default?.sendEvent(with: "app_opened", params: [:])
}
# Push banner not visible when the app is in the foreground
This is expected behavior. When your app is active, the SDK intercepts incoming push notifications and passes only .badge and .sound to the system - no banner. Instead, Positive User delivers an in-app message for foreground communication.
If you need to show a native banner in the foreground regardless, implement RemoteNotificationDelegate and handle the presentation yourself.
# In-app message doesn't appear
In-app messages are only displayed when the app is in the foreground (applicationState == .active). If the trigger fires while the app is backgrounded or suspended, the message is silently dropped - it won't appear when the app returns to the foreground.
If you're not seeing in-app messages at all, also check:
registerForRemoteNotificationshas been called- The
GoogleService-Info.plistis correctly configured - The user exists (i.e.,
ping()has completed successfully)
# Compile error when using the SDK in an app extension
UserSDK is not available in app extensions - the entire class is marked @available(iOSApplicationExtension, unavailable). If you're getting a compile error in a Notification Service Extension or other extension target, this is why.
For Notification Service Extensions specifically, use NotificationExtensionHelper - it's the only SDK class available in that context. See Push Notifications.
# FAQ
What if I have two SDK Admin Keys configured in Positive User?
Positive User will use both keys to attempt delivery. Having multiple keys doesn't cause errors, but make sure all active keys correspond to Firebase projects that are still valid - an expired or deleted key will generate delivery errors in the dashboard.
Can one FCM token belong to multiple contacts?
No. When a token is assigned to contact A and the same token already exists on contact B, it's automatically removed from B and attached to A. This happens at the moment of assignment - no manual cleanup needed.
A common scenario: an anonymous contact opens the app and gets a token registered. When they log in and tracking switches to their existing identified contact, the token moves with them.
Which token gets used when a contact has multiple devices?
Positive User always delivers to the most recently registered token. If a contact uses two apps (or two devices) and both pass their tokens, the push goes to whichever app last called register() / ping(). When that app calls again, it becomes active again.
If a token is removed and the contact still has older tokens stored (from other devices or apps), the next most recent one becomes active automatically.
# Still stuck?
Check the iOS SDK sample project (opens new window) for a working reference implementation.