UNPKG

@freshworks/react-native-freshdesk-sdk

Version:
705 lines (530 loc) 31.9 kB
# Troubleshooting ## Diagnostics-first workflow When Freshdesk integration issues are unclear, run diagnostics before changing code: ```typescript import FreshdeskSDK from '@freshworks/react-native-freshdesk-sdk'; await FreshdeskSDK.enableDebugLogs(true); const report = await FreshdeskSDK.runDiagnostics(); console.log(report.prettyPrinted); ``` Process checks in order: any `fail` first, then `warn`, then `skipped`. Apply each check's `fixHint` verbatim. Re-run diagnostics after every fix until `overallStatus` is `pass` and the symptom is resolved. On **iOS**, diagnostics cover config, network, remote config, JWT, push, widget, and runtime checks (requires FreshdeskSDK 1.3+). On **Android**, the wrapper returns integration checks plus `runtime.diagnostics: skipped` — use `debugMode: true` on `initialize()` and inspect Logcat for native SDK logs. For AI-assisted integration and debugging, copy the **AI Integration Kit** from `node_modules/@freshworks/react-native-freshdesk-sdk/ai-integration-kit/` into your app repo. See [ai-integration-kit/README.md](../../ai-integration-kit/README.md). ### Android `openSupport()` Spinner / Blank Widget **Problem:** Diagnostics show `runtime.sdkInitialized: pass`, but the widget opens with an endless loading spinner or blank content. **Common causes:** 1. **Host missing scheme** — Host was `yourcompany.freshdesk.com` instead of `https://yourcompany.freshdesk.com`. The SDK auto-prefixes `https://` from wrapper **1.2.2+**; on older versions, update `.env` manually. 2. **Double initialization on Android** — Native `FreshdeskSDK.initialize()` in `MainApplication.onCreate()` **and** JS `FreshdeskSDK.initialize()` conflict. Diagnostics may show `runtime.doubleInit: warn`. 3. **JWT enforced but no token** — User state stays `jwtNotPresent`; widget cannot load content. **Solutions:** 1. Prefer `FRESHDESK_HOST=https://yourcompany.freshdesk.com` in `.env` (bare domains also work on 1.2.2+). 2. **Remove** native init from `MainApplication.onCreate()`. Use JS init for in-app support. For headless FCM only, initialize natively inside `FirebaseMessagingService` (see sample app). 3. Pass a valid `jwt` at init when the widget enforces JWT. ### iOS `pod install` Fails — `native-versions.json` Not Found **Problem:** ```text No such file or directory @ rb_sysopen - .../native-versions.json ``` **Cause:** Published npm tarball before **1.2.2** omitted `native-versions.json`, which the podspec reads for the iOS SPM pin. **Solution:** Upgrade to `@freshworks/react-native-freshdesk-sdk@1.2.2` or later, then `cd ios && pod install`. ## Common Issues ### "Native module not found" Error **Problem:** The app throws "Freshdesk native module not found" error. **Solutions:** 1. Ensure the library is installed: ```bash npm install @freshworks/react-native-freshdesk-sdk ``` 2. iOS - Reinstall pods: ```bash cd ios && pod install ``` 3. Clean and rebuild: - iOS: `rm -rf ios/build ios/Pods && cd ios && pod install` - Android: `cd android && ./gradlew clean` 4. Restart the Metro bundler and rebuild the app. ### App Shows "Could not connect to development server" **Problem:** The app builds and installs, then shows a red error screen with: ``` Could not connect to development server. URL: http://localhost:8081/index.bundle?platform=android... java.net.ConnectException: Failed to connect to localhost/127.0.0.1:8081 ... ECONNREFUSED ``` **Cause:** This is a runtime (not build) issue — the native app installed fine, but it can't reach the Metro JS bundler. Either Metro isn't running on port 8081, or the device can't route `localhost:8081` to your machine. **Solutions:** 1. Start Metro and leave it running in its own terminal: ```bash cd sample_app && npm start ``` `npm run android` only builds/installs the app; it expects Metro to be running separately. 2. For a USB-connected Android device/emulator, forward the port so `localhost` resolves to your machine: ```bash adb reverse tcp:8081 tcp:8081 ``` Confirm the device is attached first with `adb devices`. 3. For a physical device on the same Wi-Fi, set **Dev Settings → Debug server host & port** to your machine's IP and port (e.g. `10.0.1.5:8081`). 4. Once Metro serves the bundle (`BUNDLE ./index.js ... 100.0%`), reload the app: press `r` in the Metro terminal, or shake the device and tap **Reload**. **Problem:** `pod install` fails, or the app fails to compile/link against the Freshdesk SDK. **Solutions (2.0.0+):** 1. Ensure your app's `Podfile` uses `platform :ios, '15.0'`. The native SDK requires iOS 15.0; a lower deployment target causes a CocoaPods "deployment target" error. 2. Nothing else Freshdesk-specific should be needed — the native SDK is a vendored, statically-linked xcframework, no `use_frameworks!`/SPM required. If you see linker errors or `no such module 'Expo'`, that's almost always leftover `~1.4.x` Podfile lines — see [iOS Linkage / Expo](#ios-linkage--expo-no-such-module-expo-mixed-staticdynamic-frameworks) below. 3. Ensure CocoaPods is recent: ```bash pod --version # 1.12+ ``` 4. Clean and reinstall: ```bash rm -rf ios/build ios/Pods ios/Podfile.lock rm -rf ~/Library/Developer/Xcode/DerivedData cd ios && pod install ``` > **Still on `~1.4.x`?** That version consumed the native iOS SDK as a > **Swift Package** via the podspec's `spm_dependency` helper (RN 0.75+, > default), pinned in `native-versions.json`, requiring > `use_frameworks! :linkage => :dynamic` (or `FRESHDESK_IOS_USE_VENDORED=1` > as an opt-out). If you're on RN 0.75+ with that SPM path and see > resolution errors, verify network access to > `github.com/freshworks-oss/freshdesk-ios-sdk` and that the pinned version > tag exists — or upgrade to 2.0.0+, which removes the SPM path (and this > whole class of problem) entirely. ### iOS Linkage / Expo (`no such module 'Expo'`, mixed static/dynamic frameworks) **Applies to 2.0.0+.** The native SDK now ships as a vendored `FreshdeskSDK.xcframework` and the podspec builds it as a **static** framework. `use_frameworks!` / `cocoapods-spm` / `spm_dependency` are **no longer required** and their presence (left over from a 1.4.x integration) is now the usual cause of iOS build breakage. **`no such module 'Expo'`** — caused by forcing dynamic-framework linkage in an Expo app. Fix: 1. Remove `use_frameworks!` and the Freshdesk SPM lines from the `Podfile` / config plugin. 2. `npx expo prebuild --clean && cd ios && pod install` Expo returns to its default static linkage and the error is gone. **Bare React Native** — remove from the `Podfile` / `Gemfile` the lines that only existed for the 1.4.x SPM path: | Remove | Why | |---|---| | `use_frameworks! :linkage => :dynamic` | not required by Freshdesk 2.0.0 | | `gem "cocoapods-spm"` / `plugin 'cocoapods-spm'` | SDK no longer uses `spm_dependency` | | `spm_dependency` lines added for Freshdesk | same | | `ENV['FRESHDESK_IOS_USE_VENDORED'] = '1'` | vendored is the only path; the env gate was removed | | `post_install` overrides added for mixed static/dynamic linkage | cause removed | Then `cd ios && rm -rf Pods Podfile.lock && pod install`. **If you still need `use_frameworks!`** for other SDKs (Firebase, Google Maps, etc.), keep it but prefer `:linkage => :static`. The Freshdesk podspec sets `s.static_framework = true`, so a static build is the expected configuration. ### iOS Build Fails with `'FreshdeskReactNative-Swift.h' file not found` **(1.4.x only — see the 2.0.0+ section above for current guidance)** **Problem:** The build fails compiling `FreshdeskNativeModule.mm` with `'FreshdeskReactNative-Swift.h' file not found`, even though the Swift sources compile fine. **Cause:** With `use_frameworks! :linkage => :dynamic`, the module builds as a framework and the auto-generated Swift→ObjC header lives **inside** it, so it must be imported as `<FreshdeskReactNative/FreshdeskReactNative-Swift.h>`. Importing it without the module prefix (`<FreshdeskReactNative-Swift.h>`) or as a quoted header only resolves for static linkage. **Solution:** Update to a release that imports the header with the framework-qualified path (the bridging file tries `<FreshdeskReactNative/FreshdeskReactNative-Swift.h>` first, then falls back for static linkage). A clean rebuild does **not** fix it on its own, since the cause is the import path, not stale artifacts. ### iOS Build Fails with `SDK does not contain 'libarclite'` **Problem:** The build fails with `SDK does not contain 'libarclite' at the path '.../usr/lib/arc/libarclite_iphoneos.a'; try increasing the minimum deployment target`. **Cause:** Recent Xcode versions removed the legacy `libarclite` archive. A pod whose deployment target is older than iOS 13 still tries to link it. **Solution:** Pin every pod target's deployment target in your `Podfile`'s `post_install`, then re-run `pod install`: ```ruby post_install do |installer| # ... existing react_native_post_install(...) call ... installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.0' end end end ``` ### App Crashes at Launch: `Library not loaded: @rpath/FreshdeskSDK.framework/FreshdeskSDK` **(1.4.x only.)** On **2.0.0+** the native SDK is a vendored, statically-linked xcframework embedded by CocoaPods' standard `[CP] Embed Pods Frameworks` phase — there is no separate SPM product that can fail to embed, so this cannot happen. Upgrade instead of chasing the fix below. **Problem:** The app builds and installs, then crashes immediately on launch with `dyld: Library not loaded: @rpath/FreshdeskSDK.framework/FreshdeskSDK ... (no such file)`. **Cause:** The native SDK is pulled in as a Swift Package via the podspec's `spm_dependency`. That helper links `FreshdeskSDK.framework` into the `FreshdeskReactNative` pod, but it does **not** embed `FreshdeskSDK.framework` into the app bundle. CocoaPods' "Embed Pods Frameworks" phase only copies pod frameworks, not SPM products — so the dynamic framework is missing at runtime. **Solution:** Require the helper shipped in the npm package (SDK **1.2.3+**) and call it from `post_install`: ```ruby require_relative '../node_modules/@freshworks/react-native-freshdesk-sdk/ios/freshdesk_post_install' post_install do |installer| # ... existing react_native_post_install(...) call ... freshdesk_post_install(installer) end ``` After updating the `Podfile`, run `pod install` and rebuild. Verify the framework is embedded: `ls <app>.app/Frameworks/` should list both `FreshdeskReactNative.framework` and `FreshdeskSDK.framework`. ### iOS Icons / Custom Fonts Render as "?" (Missing Glyphs) **Problem:** On iOS, `react-native-vector-icons` (or any bundled custom font) renders as `?` placeholder boxes, even though `UIAppFonts` lists the `.ttf` in `Info.plist`. Android renders the same icons correctly. **Cause:** This happens whenever the app's `Podfile` enables `use_frameworks! :linkage => :dynamic` for its own reasons (Freshdesk 2.0.0+ does not require or enable it itself). With dynamic frameworks, a pod's font resources (e.g. `react-native-vector-icons`' `s.resources = "Fonts/*.ttf"`) are bundled **inside that pod's framework** (`RNVectorIcons.framework`) instead of the main app bundle. iOS only loads fonts declared in `UIAppFonts` from the **main app bundle**, so the lookup fails and glyphs fall back to `?`. The CocoaPods "[CP] Copy Pods Resources" phase does not copy the font into the app bundle under `use_frameworks!`. **Solution:** Bundle the font into the **app target** directly so it lands in the main bundle: 1. Copy the font(s) you use into your iOS project, e.g. `ios/<app>/Fonts/MaterialCommunityIcons.ttf` (source: `node_modules/react-native-vector-icons/Fonts/`). 2. Add the font to the app target's **Copy Bundle Resources** build phase (drag it into the target in Xcode, or add it to the target's `Resources` phase in `project.pbxproj`). 3. Declare it in the app's `Info.plist` under `UIAppFonts`: ```xml <key>UIAppFonts</key> <array> <string>MaterialCommunityIcons.ttf</string> </array> ``` 4. Rebuild. Confirm the font is in the bundle: `ls <app>.app/MaterialCommunityIcons.ttf`. > Tip: `npx react-native-asset` (with a `react-native.config.js` `assets` entry) automates > steps 1–3. Only bundle the specific font files your app actually imports to keep the app size down. ### Android Build Fails: Kotlin Metadata Version Mismatch **Problem:** `:app:compileDebugKotlin` fails with: ```text Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 2.1.0, expected version is 1.9.0. ``` **Cause:** Freshdesk Android native SDK 2.2.x uses Kotlin 2.1 metadata. React Native 0.75 uses Kotlin 1.9.x. The host `:app` module compiles against Freshdesk without `-Xskip-metadata-version-check`. **Solution:** Apply the consumer Gradle snippet from the npm package (SDK **1.2.3+**) in root `android/build.gradle`: ```gradle apply from: file("../../node_modules/@freshworks/react-native-freshdesk-sdk/android/freshdesk-consumer.gradle") ``` Also set `kotlinOptions` on the app module (see [installation.md](installation.md)). Do **not** bump `kotlinVersion` to 2.1 on RN 0.75 — it breaks the React Native Gradle plugin. ### Android Build Fails with `26.0.1` **Problem:** `./gradlew` fails immediately with `What went wrong: 26.0.1` and no other context. **Cause:** Gradle 8.8 (and the embedded Kotlin compiler) does not support running on JDK 26. This happens when `JAVA_HOME` points to a JDK newer than 21. **Solutions:** 1. Build with JDK 17 (recommended for React Native Android): ```bash export JAVA_HOME=$(/usr/libexec/java_home -v 17) cd sample_app/android && ./gradlew clean cd .. && npx react-native run-android ``` 2. Pin JDK 17 for Gradle only by adding this to `sample_app/android/gradle.properties` (use your local JDK 17 path): ```properties org.gradle.java.home=/Users/you/Library/Java/JavaVirtualMachines/ms-17.0.19/Contents/Home ``` 3. Make JDK 17 the default in your shell profile so Android builds always use it: ```bash export JAVA_HOME=$(/usr/libexec/java_home -v 17) ``` ### Android Build Fails with Kotlin "Type mismatch" in `react-native-screens` / `react-native-gesture-handler` **Problem:** `compileDebugKotlin` fails for `:react-native-screens` and/or `:react-native-gesture-handler` with errors like: ``` ScreenViewManager.kt: Type mismatch: inferred type is StateWrapper? but StateWrapper was expected RNGestureHandlerTouchEvent.kt: Type mismatch: inferred type is View? but View was expected ``` **Cause:** These libraries were compiled against an older React Native API surface. React Native 0.75 tightened nullability annotations on core APIs (`ViewManager.updateState`'s `StateWrapper` parameter and `UIManagerHelper.getSurfaceId(View)`), so versions of these libraries released before RN 0.75 no longer compile. This is a **library-version mismatch**, not a Kotlin toolchain issue (RN 0.75 already uses the correct Kotlin 1.9.24). **Solution:** Upgrade both navigation libraries to RN 0.75-compatible versions in your app's `package.json`, then reinstall: ```jsonc { "dependencies": { "react-native-screens": "3.34.0", // first release with RN 0.75 support "react-native-gesture-handler": "2.20.2" // RN 0.75 supported (>= 2.18.0) }, "overrides": { "react-native-gesture-handler": "2.20.2" } } ``` ```bash npm install cd android && ./gradlew clean ``` The `sample_app` is pinned to these versions for RN 0.75.4. ### Android "Could not resolve" Dependency Error **Problem:** Gradle fails to resolve `com.freshworks.sdk:freshdesk`. **Solutions:** 1. Verify `mavenCentral()` is in repositories: ```gradle allprojects { repositories { google() mavenCentral() } } ``` 2. Sync project with Gradle files in Android Studio. 3. Check network connectivity to Maven Central. ### SDK Initialization Fails **Problem:** `initialize()` throws an error or never completes. **Cause:** Initialization requires only `token`, `host`, and `sdkId`. Missing push notification configuration (Firebase, APNs, portal push keys) does **not** block initialization — in-app support works without push. If `initialize()` rejects with `FRESHDESK_INIT_ERROR`, check network connectivity and that credentials are valid. On Android, the promise now rejects explicitly when remote config fetch fails instead of hanging indefinitely. **Solution:** 1. Verify `token`, `host`, and `sdkId` from Admin Settings → Mobile Chat SDK. 2. Confirm network access from the device/emulator. 3. For JWT-enforced widgets, pass a valid `jwt` at init. 4. Do not treat missing Firebase/`google-services.json` or APNs setup as an init blocker — add push wiring only when you need tray notifications. 5. Check console for specific error messages: - `FRESHDESK_INVALID_CONFIG` - Missing parameters - `FRESHDESK_INIT_ERROR` - Server/connection issue or remote config fetch failure ### Events Not Firing **Problem:** Event listeners not receiving events. **Solutions:** 1. Ensure SDK is initialized before setting listeners. 2. Check listener is properly set up: ```typescript const subscription = FreshdeskSDK.addUnreadCountListener((event) => { console.log(event); }); ``` 3. Clean up and re-add listeners after app state changes. 4. On Android, verify `LocalBroadcastManager` is working. 5. On iOS, ensure you are on a release where the native module registers itself as the `RCTEventEmitter` (the Objective-C `FreshdeskNativeModule` sets the emitter on the Swift bridge in `-init`). On older builds the emitter was never wired up, so native notifications (`unreadCountChanged`, `userStateChanged`, `userCreated`, `onLinkPressed`) were silently dropped. A common symptom is the **initial unread count showing correctly** (it comes from the direct `getUnreadCount()` call) while **real-time updates never arrive** and **User State stays `unknown`** (both rely on events). Update to a fixed release and rebuild. ### openSupport() Shows Blank Screen **Problem:** Support screen opens but is blank. **Solutions:** 1. Ensure SDK is initialized successfully before calling `openSupport()`. 2. Check iOS deployment target is 15.0+. 3. Verify network connectivity. 4. Check Freshdesk credentials are valid. ### openSupport() / trackEvent() / setUserProperties() Silently Do Nothing Right After initialize() (iOS) **Problem:** `initialize()` resolves without throwing, but the very next call — `openSupport()`, `trackEvent()`, `setUserProperties()`, or `setTicketProperties()` — appears to do nothing: no UI opens, no error is thrown, no data reaches the Freshdesk dashboard. Often intermittent — it works on a retry a moment later, or more reliably on a fast network. The native SDK may log: ``` ⚠️ [Freshdesk Warning] Tasks will be executed once the SDK is loaded, Check whether the SDK is initialised with proper configuration. ``` **Cause:** The native iOS SDK's `Freshdesk.initialize(with:)` has no completion callback, `async` variant, or any readiness signal of its own — it does its own async internal loading after `initialize()` returns, and any call made before that finishes is silently queued/dropped by the native SDK itself (not by this wrapper). On SDK versions before the fix noted below, the wrapper resolved `initialize()`'s JS promise the instant the native call *returned*, not when the SDK was actually ready, so a call issued right after `await initialize()` — completely normal usage — could race the real load and lose. **Solution:** Upgrade to an SDK version with the `initialize()` settle-delay fix (see `CHANGELOG.md`'s "iOS `initialize()` settle delay" entry) — `initialize()` now resolves only once the SDK has had time to actually finish loading, so plain `await initialize()` usage becomes safe on its own; no app code change needed. **Expect `initialize()` to take at least ~2 seconds on iOS as a result** — that is expected, not a regression. On a version without the fix, or as a belt-and-braces measure: add a short delay (1–2s) after `initialize()` resolves before making the first other SDK call. ### JWT Authentication Issues **Problem:** User state stuck in `notAuthenticated` or `authExpired`. **Solutions:** 1. Verify JWT is correctly formatted and signed. 2. Check JWT is not expired. 3. For JWT-enforced SDKs, ensure widget settings match: - Go to Admin Settings -> Mobile Chat SDK - Verify "Enforce JWT" is enabled/disabled as expected 4. Listen for `userStateChanged` events to debug. ### Push Notifications Not Working **Problem:** Not receiving push notifications from Freshdesk. **Solutions (iOS):** 1. Confirm the **Push Notifications** capability + **Background Modes → Remote notifications** are enabled on the app target in Xcode. The Push Notifications capability links `quickbasket/quickbasket.entitlements` (`aps-environment`); without it, `didFailToRegisterForRemoteNotificationsWithError` fires. 2. Ensure the SDK is **initialized natively** in `AppDelegate didFinishLaunchingWithOptions` (via `FreshdeskPush.initialize`). The APNs token is registered at launch, before the JS layer runs `initialize()`; `setPushRegistrationToken` is a no-op until the SDK is initialized, so JS-only init drops the token. Verify the `Freshdesk*` keys exist in `Info.plist`. 3. Upload the APNs **`.p8`** auth key (with Key ID + Team ID) in the Freshdesk portal. 4. Test on a **real device** — the Simulator never receives remote pushes. 5. Verify the device token reaches the SDK: `AppDelegate``didRegisterForRemoteNotificationsWithDeviceToken``FreshdeskPush.registerToken(...)`. If `didFailToRegisterForRemoteNotificationsWithError` fires, the capability/provisioning is missing. ### Push Received in Foreground but Not in Background / Killed State (iOS) **Problem:** Freshdesk notifications appear while the app is open (foreground), but nothing arrives when the app is backgrounded or killed. **Cause:** `AppDelegate` only forwards pushes from `willPresentNotification:` (foreground) and `didReceiveNotificationResponse:` (notification tapped). When the app is backgrounded or relaunched in the background, iOS delivers the payload through `application:didReceiveRemoteNotification:fetchCompletionHandler:`. If that method is not implemented (or it does not call `FreshdeskPush.handleRemoteNotification`), the SDK never sees the background payload and no notification is processed/displayed. **Solution:** 1. Implement the background delivery handler in `AppDelegate` and forward Freshdesk payloads to the SDK (the `sample_app` includes this): ```objc - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { if ([FreshdeskPush isFreshdeskNotification:userInfo]) { [FreshdeskPush handleRemoteNotification:userInfo applicationState:application.applicationState]; completionHandler(UIBackgroundFetchResultNewData); return; } completionHandler(UIBackgroundFetchResultNoData); } ``` 2. Confirm `UIBackgroundModes` includes `remote-notification` in `Info.plist` and that **Background Modes → Remote notifications** is enabled on the app target. iOS only wakes a backgrounded/terminated app for the handler above when this mode is set. 3. The push payload must include `content-available: 1` in its `aps` dictionary for iOS to wake the app in the background. Freshdesk sends this for its data pushes; if you have a custom push proxy, make sure it is preserved. 4. Note the user-force-quit caveat: if the user **manually swipes the app away** from the app switcher, iOS suppresses background `content-available` wakeups until the app is launched again. A visible alert push still appears (rendered by the system), and tapping it launches the app and routes through `didReceiveNotificationResponse:`. This is expected iOS behavior, not an SDK bug. **Solutions (Android):** 1. Ensure **`google-services.json`** is in `android/app/` and the **Google Services plugin** is enabled (uncomment the classpath in `android/build.gradle` and `apply plugin` in `android/app/build.gradle`). 2. Upload your **FCM credentials** in the Freshdesk portal. 3. Confirm `FreshdeskMessagingService` is registered in `AndroidManifest.xml` and that the device has Google Play services. 4. On Android 13+, grant the `POST_NOTIFICATIONS` runtime permission. 5. Verify the token reaches the SDK in `FreshdeskMessagingService.onNewToken``FreshdeskSDK.setPushRegistrationToken(token)`. 6. Ensure the SDK is **initialized natively** in `MainApplication.onCreate()`. Push methods are no-ops until the SDK is initialized; initializing only from JavaScript (`FreshdeskContext`) means the token is registered before init completes (and dropped), and background/killed pushes are ignored because the JS layer never runs in a headless FCM delivery. Check Logcat for `FreshdeskPush: Freshdesk SDK initialized natively (push-ready)`; if you instead see `SDK is not initialized`, native init did not run (verify `.env` credentials are present and surfaced via `BuildConfig`). ### Push Shown In-App but Not in the Notification Tray (iOS) **Problem:** Freshdesk notifications appear while the app is open (foreground / in-app), but nothing shows in the system notification tray when the app is in the background or killed. **Cause:** The Freshdesk SDK's push methods (`handleRemoteNotification`) only post a tray notification once the SDK is initialized. When the app is **cold-launched in the background by a push**, iOS calls `application:didReceiveRemoteNotification:fetchCompletionHandler:` right after `didFinishLaunchingWithOptions` returns. If native init is dispatched asynchronously, that handler can run **before** init finishes, so the payload is dropped and no tray notification is posted. The same push works in the foreground because the SDK is already initialized. **Solution:** Initialize the SDK **synchronously** at launch so it is push-ready before the background delivery handler runs. The SDK's native entry point (`FreshdeskNativeModuleBridge.initializeSDK`, driven by `FreshdeskPush.initializeSDK` from `AppDelegate didFinishLaunchingWithOptions`) initializes synchronously on the main thread for exactly this reason. If you wire init yourself, do not defer it to a later run-loop turn (`DispatchQueue.main.async`) — run it inline in `didFinishLaunchingWithOptions` so it completes before iOS delivers the launching push. ### Push Shown In-App but Not in the Notification Tray (Android) **Problem:** Freshdesk notifications appear while the app is open (foreground / in-app), but nothing shows in the system notification tray when the app is in the background or killed. **Cause:** `FreshdeskSDK.initialize(...)` is **asynchronous** — its completion callback fires only after the SDK is fully set up, and `handleFCMNotification` / `setPushRegistrationToken` are **no-ops until then**. On a headless FCM delivery (app killed/background), Android starts the process to run only `FreshdeskMessagingService`. `MainApplication.onCreate()` merely *starts* the async init, so `onMessageReceived` can run and call `handleFCMNotification` **before init finishes** — the message is dropped and no tray notification is posted. The same push works while the app is already running because the SDK is already initialized. **Solution:** Have the FCM service **wait for initialization to complete** before forwarding the message. The `sample_app` routes init through a shared, idempotent `FreshdeskInitializer` that both `MainApplication.onCreate()` and `FreshdeskMessagingService` use; the service calls `FreshdeskInitializer.ensureInitializedBlocking(applicationContext)` before `FreshdeskSDK.handleFCMNotification(data)` (and before `setPushRegistrationToken` in `onNewToken`). `onMessageReceived` runs on a background thread, so the short, bounded wait is safe. If you wire push yourself, guarantee the SDK is initialized before calling any push method in the service. ## Error Codes Reference Import the typed enum and compare against it instead of matching the string literal directly: ```typescript import { FreshdeskErrorCode } from '@freshworks/react-native-freshdesk-sdk'; try { await FreshdeskSDK.openSupport(); } catch (error) { if (error.code === FreshdeskErrorCode.NOT_INITIALIZED) { /* ... */ } } ``` Coverage is **not identical on both platforms** — a code marked (Android) or (iOS) is only ever rejected on that platform; unmarked codes can occur on either. | Error Code | Platform | Description | Solution | |------------|----------|-------------|----------| | `FRESHDESK_INVALID_CONFIG` | Both | `initialize()`'s config was missing a required key or malformed | Check token, host, sdkId are provided | | `FRESHDESK_NOT_INITIALIZED` | Both | A method other than `initialize()` was called before `initialize()` resolved | Call `initialize()` first, await it | | `FRESHDESK_INIT_TIMEOUT` | Android | `initialize()` timed out (20s) waiting for the native SDK to report ready | Verify token/host/sdkId, network reachability, JWT settings | | `FRESHDESK_INIT_ERROR` | Android | `initialize()` threw before it could start | Check credentials and network | | `FRESHDESK_NOT_READY` | Android | `initialize()` resolved but the native SDK isn't ready yet | Retry shortly — self-resolves | | `FRESHDESK_NO_ACTIVITY` | Android | `openSupport()`/`openKnowledgeBase()`/`openTopic()` had no foreground Activity to attach to | Ensure app is foregrounded | | `FRESHDESK_NO_VIEW_CONTROLLER` | iOS | `openSupport()`/`openKnowledgeBase()`/`openTopic()` had no view controller to present from | Ensure app is foregrounded | | `FRESHDESK_OPEN_ERROR` | Android | `openSupport()`/`openKnowledgeBase()`/`openTopic()` failed to present the native UI | Check SDK is initialized; on iOS, see the [silent-failure section above](#opensupport--trackevent--setuserproperties-silently-do-nothing-right-after-initialize-ios) | | `FRESHDESK_TRACK_ERROR` | Android | `trackEvent()` failed | Check SDK is initialized | | `FRESHDESK_USER_PROPERTIES_ERROR` | Both | `setUserProperties()` failed | Check SDK is initialized | | `FRESHDESK_TICKET_PROPERTIES_ERROR` | Android | `setTicketProperties()` failed | Check SDK is initialized | | `FRESHDESK_AUTH_ERROR` | Android | `authenticateAndUpdate()` failed | Verify JWT is valid | | `FRESHDESK_DISMISS_ERROR` | Android | `dismiss()` failed | Check SDK is initialized | | `FRESHDESK_USER_ERROR` | Both | `getUser()` failed, or its response could not be parsed | Check SDK is initialized and network | | `FRESHDESK_USER_PARSE_ERROR` | iOS | `getUser()`'s response could not be parsed | Report with SDK version — likely a native response-shape issue | | `FRESHDESK_CONFIG_PARSE_ERROR` | Both | `setContentConfiguration()`'s JSON payload could not be parsed | Check the config object shape | ## Debug Mode Enable debug logging on Android: ```typescript await FreshdeskSDK.initialize({ // ... config debugMode: true, }); ``` Check native logs: - iOS: Xcode console or `Console.app` - Android: Android Studio Logcat or `adb logcat` ## Getting Help If issues persist: 1. Check [GitHub Issues](https://github.com/freshworks/freshdesk_react_native_sdk/issues) 2. Contact Freshdesk support: support@freshdesk.com 3. Include error logs and SDK version in your report