React-native-firebase: 馃敟Crashlytics: recordError method not working on iOS

Created on 2 May 2020  路  15Comments  路  Source: invertase/react-native-firebase


Issue



I am adding recordError calls to my app on each catch clause in Javascript.

try {
    ...
} catch (error) {
    console.error(error)
    crashlytics().recordError(error)
}

I then test it by throwing a Javascript error in the try clause

try {
    ...
    throw new Error('test error')
} catch (error) {
    console.error(error)
    crashlytics().recordError(error)
}

After I confirm through the chrome debug console that the error was triggered and recordError was called, I close the app and re-open it (I read somewhere that errors report only after you reopen the app. Not sure if it applies to recordError, but did it just in case)

I expected this error to be reported in Crashlytics, but it never reports.

If I force a native crash inside the try clause, the native error does report into Crashlytics:

try {
    ...
    crashlytics().crash()
} catch (error) {
    console.error(error)
    crashlytics().recordError(error)
}

The javascript error doesn't report. Just the native


Project Files






Javascript

Click To Expand

#### `package.json`:

{
  "name": "myapp",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "react-native start",
    "test": "jest",
    "android": "adb reverse tcp:8081 tcp:8081 && cd ./android && ./gradlew app:assembleDebug && ./gradlew installDebug",
    "androidPrepRelease": "cd ./android && ./gradlew app:assembleRelease",
    "androidInstallRelease": "cd ./android && ./gradlew app:assembleRelease && adb install ./app/build/outputs/apk/release/app-release.apk",
    "network": "adb reverse tcp:8081 tcp:8081",
    "cc": "watchman watch-del-all && rm -rf $TMPDIR/react-* && rm -rf $TMPDIR/metro-* && rm -rf $TMPDIR/haste-* && npm cache clean --force",
    "prepare": "patch-package",
    "postinstall": "npx jetify"
  },
  "dependencies": {
    "@react-native-community/netinfo": "^5.6.2",
    "@react-native-community/push-notification-ios": "^1.0.7",
    "@react-native-firebase/app": "6.4.1-alpha.0",
    "@react-native-firebase/crashlytics": "6.4.1-alpha.0",
    "@react-native-firebase/messaging": "6.4.1-alpha.0",
    "axios": "^0.19.2",
    "i18n-js": "^3.5.1",
    "jsc-android": "^241213.1.0",
    "mobx": "^5.15.4",
    "mobx-persist": "^0.4.1",
    "mobx-react": "^5.4.3",
    "moment": "^2.24.0",
    "pusher-js": "^5.1.1",
    "react": "16.9.0",
    "react-native": "0.61.5",
    "react-native-actionsheet": "^2.4.2",
    "react-native-autolink": "^2.0.0",
    "react-native-image-crop-picker": "^0.28.0",
    "react-native-keyboard-aware-scrollview": "^2.1.0",
    "react-native-navigation": "^6.2.0",
    "react-native-photo-view": "https://github.com/thanhcuong1990/react-native-photo-view.git",
    "react-native-push-notification": "^3.1.9",
    "react-native-swipe-list-view": "^2.3.0",
    "react-native-vector-icons": "^6.6.0"
  },
  "devDependencies": {
    "@babel/core": "^7.6.2",
    "@babel/plugin-proposal-decorators": "^7.0.0-beta.47",
    "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0-beta.47",
    "@babel/plugin-proposal-optional-chaining": "^7.0.0-beta.47",
    "@babel/plugin-transform-flow-strip-types": "^7.0.0-beta.47",
    "@babel/runtime": "^7.6.2",
    "@react-native-community/eslint-config": "^0.0.5",
    "babel-jest": "^24.9.0",
    "babel-preset-mobx": "^2.0.0",
    "babel-preset-react-native": "^5.0.0",
    "eslint": "^6.5.1",
    "jest": "^24.9.0",
    "jetifier": "^1.6.5",
    "metro-react-native-babel-preset": "^0.56.0",
    "patch-package": "^6.1.4",
    "react-test-renderer": "16.9.0"
  },
  "jest": {
    "preset": "react-native"
  }
}

#### `firebase.json` for react-native-firebase v6:
{
  "react-native": {
    "crashlytics_debug_enabled": true,
    "crashlytics_auto_collection_enabled": true
  }
}

### iOS
Click To Expand

#### `ios/Podfile`: - [ ] I'm not using Pods - [x] I'm using Pods and my Podfile looks like:

# Uncomment the next line to define a global platform for your project
platform :ios, '9.0'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

target 'myapp' do
  pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector"
  pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec"
  pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired"
  pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety"
  pod 'React', :path => '../node_modules/react-native/'
  pod 'React-Core', :path => '../node_modules/react-native/'
  pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules'
  pod 'React-Core/DevSupport', :path => '../node_modules/react-native/'
  pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS'
  pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation'
  pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob'
  pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image'
  pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS'
  pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network'
  pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings'
  pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text'
  pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration'
  pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/'

  pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact'
  pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
  pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
  pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
  pod 'ReactCommon/jscallinvoker', :path => "../node_modules/react-native/ReactCommon"
  pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon"
  pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga'

  pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
  pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
  pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'

  pod 'RNImageCropPicker', :path =>  '../node_modules/react-native-image-crop-picker'

  target 'myappTests' do
    inherit! :search_paths
    # Pods for testing
  end

  use_native_modules!
end

target 'myapp-tvOS' do
  # Pods for RnDiffApp-tvOS
  target 'myapp-tvOSTests' do
    inherit! :search_paths
    # Pods for testing
  end
end

#### `AppDelegate.m`:
#import <UserNotifications/UserNotifications.h>
#import "AppDelegate.h"
#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <ReactNativeNavigation/ReactNativeNavigation.h>
#import <Firebase.h>
#import <RNCPushNotificationIOS.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  if ([FIRApp defaultApp] == nil) {
    [FIRApp configure];
  }

  UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
  center.delegate = self;

  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];

  [ReactNativeNavigation bootstrap:[self sourceURLForBridge: bridge] launchOptions:launchOptions];

  return YES;
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
  [RNCPushNotificationIOS didRegisterUserNotificationSettings:notificationSettings];
}

// Required for the register event.
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
  [RNCPushNotificationIOS didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}

// Required for the notification event. You must call the completion handler after handling the remote notification.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
  [RNCPushNotificationIOS didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}

// Required for the registrationError event.
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
  [RNCPushNotificationIOS didFailToRegisterForRemoteNotificationsWithError:error];
}

// Required for the localNotification event.
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
  [RNCPushNotificationIOS didReceiveLocalNotification:notification];
}

// Called when a notification is delivered to a foreground app.
  -(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
  {
    completionHandler(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge);
  }

@end


I am not working with Android


Environment

Click To Expand

**`react-native info` output:**

 System:
    OS: macOS 10.15.3
    CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 104.89 MB / 16.00 GB
    Shell: 5.7.1 - /bin/zsh
  Binaries:
    Node: 10.16.0 - ~/.nvm/versions/node/v10.16.0/bin/node
    Yarn: 1.22.4 - /usr/local/bin/yarn
    npm: 6.9.0 - ~/.nvm/versions/node/v10.16.0/bin/npm
    Watchman: 4.9.0 - /usr/local/bin/watchman
  SDKs:
    iOS SDK:
      Platforms: iOS 13.4, DriverKit 19.0, macOS 10.15, tvOS 13.4, watchOS 6.2
  IDEs:
    Xcode: 11.4.1/11E503a - /usr/bin/xcodebuild
  npmPackages:
    react: 16.9.0 => 16.9.0 
    react-native: 0.61.5 => 0.61.5
- **Platform that you're experiencing the issue on**: - [X] iOS - [ ] Android - [X] **iOS** but have not tested behavior on Android - [ ] **Android** but have not tested behavior on iOS - [ ] Both - **`react-native-firebase` version you're using that has this issue:** - `6.4.1-alpha.0` - **`Firebase` module(s) you're using that has the issue:** - `@react-native-firebase/crashlytics 6.4.1-alpha.0` - **Are you using `TypeScript`?** - `No`




Needs Triage Bug iOS Crashlytics >= 6

Most helpful comment

And turns out it shows up in the console after all. 馃槄 The only remaining issue seems to be that by default recordCustomExceptionName:reason:frameArray: doesn't log events as type "crash". So they don't show up on the console unless you disable the default filter! And also seem to take some delay. Maybe that'll also fix your issue @embpdaniel.

image

All 15 comments

Hi there! Current version is 6.7.1 now though I don't think that will change things.
Are you in debug mode? Try release, just out of curiosity

@mikehardy I tried what you suggested (upgraded to 6.7.1) and also built a production build, but no luck. No errors are being logged from recordError. Do you have any ideas?

Unsure - I did just check through those docs while reviewing #3580 and they have some pretty specific callouts about the difference between a crash and a recorded error. I don't have personal experience and don't want to mislead by misquoting the docs but I recommend you check upstream SDK docs to see what they have to say on the differences and see if that's possibly related?

Hello 馃憢, to help manage issues we automatically close stale issues.
This issue has been automatically marked as stale because it has not had activity for quite some time. Has this issue been fixed, or does it still require the community's attention?

This issue will be closed in 15 days if no further activity occurs.
Thank you for your contributions.

I can confirm this is still happening with

"@react-native-firebase/app": "^7.3.0",
"@react-native-firebase/auth": "^8.0.7",

A simple crashlytics().recordError(new Error('test')) does not show up on the console for me, whereas crashlytics().crash() works. The PR looks great, though I can't pinpoint if that would fix anything here.

Not sure if the PR for switch to crashlytics will affect it or not but I'm hesitant to spend any time until that PR is integrated. Let me see if I can nudge that one, in the meantime, the quickest way to move this forward is to move into the module via direct addition of console.log() calls in the javascript for this module inside node_modules and the same but in the Objective-C underneath the javascript to see if everything is actually being called. That will help us determine if it's a problem here in this module or in the underlying API.

I did a tiny bit of print debugging. I can confirm that on the JS side,

this.native.recordError(createNativeErrorObj(error, stackFrames, false))

(index.js line 118) is getting called successfully. On the native Objective-C side,

RCT_EXPORT_METHOD(recordError: (NSDictionary *) jsErrorDict)

is also being called and we make it all the way to the

[[Crashlytics sharedInstance] recordCustomExceptionName:name reason:message frameArray:customFrames]

call, it seems.

There, name, message, and customFrames all look good. customFrames seems to include the kind of JavaScript stack stuff I'd want to see in the console. (The filenames don't seem to make it -- everything is attributed to index.bundle -- but it's still helpful.)

2020-06-29 14:40:46.486185-0700 [][16995:2647541] Name: JavaScriptError
2020-06-29 14:40:46.486275-0700 [][16995:2647541] Message: test
2020-06-29 14:40:46.486893-0700 [][16995:2647541] customFrames: (
    "{[0x0] http://192.168.86.156:8081/index.bundle:128763:58 - componentDidMount:128763}",
    "{[0x0] http://192.168.86.156:8081/index.bundle:24793:45 - commitLifeCycles:24793}",
    "{[0x0] http://192.168.86.156:8081/index.bundle:27137:29 - commitLayoutEffects:27137}",
    "{[0x0] http://192.168.86.156:8081/index.bundle:13277:21 - invokeGuardedCallbackImpl:13277}",
    "{[0x0] http://192.168.86.156:8081/index.bundle:13373:42 - invokeGuardedCallback:13373}",
    "{[0x0] http://192.168.86.156:8081/index.bundle:26944:36 - commitRootImpl:26944}",
    "{[0x0] [native code]:0:0 - commitRootImpl:0}",
    "{[0x0] http://192.168.86.156:8081/index.bundle:42737:30 - unstable_runWithPriority:42737}",
    "{[0x0] http://192.168.86.156:8081/index.bundle:26806:24 - commitRoot:26806}",
    "{[0x0] [native code]:0:0 - commitRoot:0}",
    "{[0x0] http://192.168.86.156:8081/index.bundle:26139:34 - runRootCallback:26139}",
    "{[0x0] [native code]:0:0 - runRootCallback:0}",
    "{[0x0] http://192.168.86.156:8081/index.bundle:16869:38 - <unknown>:16869}",
    "{[0x0] http://192.168.86.156:8081/index.bundle:42737:30 - unstable_runWithPriority:42737}",
    "{[0x0] http://192.168.86.156:8081/index.bundle:16864:28 - flushSyncCallbackQueueImpl:16864}",
    "{[0x0] http://192.168.86.156:8081/index.bundle:16853:35 - flushSyncCallbackQueue:16853}",
    "{[0x0] http://192.168.86.156:8081/index.bundle:26021:37 - scheduleUpdateOnFiber:26021}",
    "{[0x0] http://192.168.86.156:8081/index.bundle:18422:23 - enqueueSetState:18422}",
    "{[0x0] http://192.168.86.156:8081/index.bundle:8666:37 - <unknown>:8666}",
    "{[0x0] http://192.168.86.156:8081/index.bundle:98201:30 - <unknown>:98201}",
    "{[0x0] http://192.168.86.156:8081/index.bundle:7549:42 - emit:7549}",
    "{[0x0] http://192.168.86.156:8081/index.bundle:98833:27 - <unknown>:98833}",
    "{[0x0] http://192.168.86.156:8081/index.bundle:7549:42 - emit:7549}",
    "{[0x0] http://192.168.86.156:8081/index.bundle:97238:43 - <unknown>:97238}",
    "{[0x0] http://192.168.86.156:8081/index.bundle:7549:42 - emit:7549}",
    "{[0x0] http://192.168.86.156:8081/index.bundle:3300:49 - __callFunction:3300}",
    "{[0x0] http://192.168.86.156:8081/index.bundle:3013:31 - <unknown>:3013}",
    "{[0x0] http://192.168.86.156:8081/index.bundle:3254:15 - __guard:3254}",
    "{[0x0] http://192.168.86.156:8081/index.bundle:3012:21 - callFunctionReturnFlushedQueue:3012}",
    "{[0x0] [native code]:0:0 - callFunctionReturnFlushedQueue:0}"
)

And turns out it shows up in the console after all. 馃槄 The only remaining issue seems to be that by default recordCustomExceptionName:reason:frameArray: doesn't log events as type "crash". So they don't show up on the console unless you disable the default filter! And also seem to take some delay. Maybe that'll also fix your issue @embpdaniel.

image

@mikehardy This can be closed as far as I'm concerned. At some point it'd be nice to think about how we could get filename consistency on the JS side. Thanks for your help!!

Okay - seems good to close then, but for the sanity of future developers you might do a PR to the docs on this API call mentioning that by default the console filters them out - this is clearly a time sink for people :-) 馃檹 - there's an edit button top-right of every docs page and the github UI makes PRs for docs really easy

There's no way to sync up file names I think? That's been discussed before but the toolchains people use to render the bundle are widely varied, the only way I can think of is to use some of the existing reverse-mapping tools based on tags from the original code in your codebase, so you can feed it the logged index.bundle-referencing stack and get your original code

I have this issue. I'm able to get crashes in firebase console but not the recordError.

"@react-native-firebase/app": "^8.2.0",
"@react-native-firebase/crashlytics": "^8.3.1",

@abdulghanitech recordError shows up fine, typically it is filtered on the console though and you have to unfilter crashes so you get errors too. Easy mistake to make, can you check?

Same for me with a slight difference:
iOS & Android: recordError errors only showed up in the dashboard, after closing the app completely (not only background) and reopen it again 馃槥. (no filter attached to the dashboard view)

@christophby: I am also facing the same issue, did you get any solution?

@sangameshrently

Unfortunately I didn't

Was this page helpful?
0 / 5 - 0 ratings