Troubleshooting
Symptom-driven debugging for the MotiSig iOS SDK.
Symptoms grouped by area. Set logLevel: .debug in MotiSig.initialize and watch the console — the SDK logs every queued mutation and HTTP failure with the prefix [MotiSig].
| Symptom | Likely cause | Fix |
|---|
MotiSig is not initialized in logs | initialize was never called, or sdkKey / projectId resolved to empty (after env-var fallback). | Call MotiSig.initialize(...) early in application(_:didFinishLaunchingWithOptions:) or your @main App.init. Confirm MOTISIG_SDK_KEY / MOTISIG_PROJECT_ID are set in the run scheme if you rely on them. See Configuration. |
| HTTP requests go to the wrong host | baseURL was not passed and MOTISIG_BASE_URL is unset. | Either pass baseURL: URL(string: "...") or set MOTISIG_BASE_URL. The default fallback is https://api.motisig.ai/client. |
401 / 403 on every request | Wrong sdkKey for the target environment. | Confirm the key matches the project. Each request sends X-API-Key and X-Project-ID headers. |
| Symptom | Likely cause | Fix |
|---|
409 Conflict on setUser | The server already has this user id. | This is expected. The SDK treats 409 as success and persists the id locally. |
triggerEvent completion never fires | Completion runs on the Swift concurrency cooperative pool, not the main queue. | Dispatch to the main actor before touching UI: await MainActor.run { ... }. |
MotiSigError.userNotSet from triggerEvent | setUser has not been called yet (or logout ran). | Call setUser before any user-scoped mutation. See User and profile. |
| Mutations sent in unexpected order | Calling code launched two mutations from different threads without awaiting. | The SDK already serializes mutations on its FIFO queue; the order is the order of enqueue, not completion. See the lifecycle in Getting started. |
| Symptom | Likely cause | Fix |
|---|
| Device token never arrives | Push capability missing on the target, or running on the iOS Simulator without a registered Apple ID. | Enable Push Notifications capability on the host app target. APNs sandbox tokens require a real provisioning profile. |
permission always unknown | The user has not yet responded to the prompt. | The SDK patches permission when the user returns from Settings. notDetermined maps to unknown until the user decides. |
| Push subscription not removed on logout | logout() was called before any APNs token arrived. | Without a token there is nothing to remove server-side; the local clear still happens. |
| Symptom | Likely cause | Fix |
|---|
MotiSigNotificationListener callback never fires | The listener object was deallocated (the SDK holds it weakly). | Retain the listener as a stored property of a long-lived object (typically your App/AppDelegate). |
| Listeners receive duplicate events | Both MotiSigNotificationListener and fetchDeliveredNotifications() returned the same notification. | Deduplicate with requestIdentifier and/or messageId. See Push notifications. |
| Click tracking not firing | Payload has no messageId, or no user is set when the tap happens. | Verify the server payload contains messageId; ensure setUser ran before the tap. Logs at .debug level will show "skipping click tracking". |
Conflict with existing UNUserNotificationCenterDelegate | Your app or another SDK installed a delegate after MotiSig.initialize. | Install yours before initialize (the SDK proxies an existing delegate) or forward willPresent / didReceive to the SDK manually. |
| AppDelegate swizzling conflict | Two SDKs swizzle application(_:didRegisterForRemoteNotificationsWithDeviceToken:). | Ensure all swizzlers chain to the previous implementation (the MotiSig swizzler does). If problems persist, open an issue with both stack traces. |
See Rich notification images for the dedicated checklist. Most common failures:
aps.mutable-content missing (NSE is never invoked).
- NSE bundle id is not a prefix-child of the host bundle id.
- Image URL is non-HTTPS or returns
403/404.
- The host app suppresses the foreground banner from its own
willPresent.
| Symptom | Likely cause | Fix |
|---|
| Integration tests skip | MOTISIG_SDK_KEY / MOTISIG_PROJECT_ID / MOTISIG_BASE_URL not set. | Set them in your test scheme or CI environment. See IntegrationTestCredentials.swift. |
| Tests register real users | Integration tests are not isolated by default. | Use a dedicated test project / API key; the SDK does not sandbox writes. |