Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🔥Crashlytics: recordError method not working on iOS #3594

Closed
3 of 7 tasks
embpdaniel opened this issue May 1, 2020 · 17 comments
Closed
3 of 7 tasks

🔥Crashlytics: recordError method not working on iOS #3594

embpdaniel opened this issue May 1, 2020 · 17 comments
Labels
help: needs-triage Issue needs additional investigation/triaging. platform: ios plugin: crashlytics Firebase Crashlytics type: bug New bug report

Comments

@embpdaniel
Copy link
Contributor

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
  • 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:
    • iOS
    • Android
    • 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


@mikehardy
Copy link
Collaborator

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

@embpdaniel
Copy link
Contributor Author

@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?

@mikehardy
Copy link
Collaborator

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?

@russellwheatley russellwheatley added the plugin: crashlytics Firebase Crashlytics label May 21, 2020
@stale
Copy link

stale bot commented Jun 20, 2020

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.

@stale stale bot added the Type: Stale Issue has become stale - automatically added by Stale bot label Jun 20, 2020
@CatalinVoss
Copy link

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.

@stale stale bot removed the Type: Stale Issue has become stale - automatically added by Stale bot label Jun 29, 2020
@mikehardy mikehardy added help: needs-triage Issue needs additional investigation/triaging. type: bug New bug report platform: ios Version: >= 6 labels Jun 29, 2020
@mikehardy
Copy link
Collaborator

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.

@CatalinVoss
Copy link

CatalinVoss commented Jun 29, 2020

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}"
)

@CatalinVoss
Copy link

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

@CatalinVoss
Copy link

@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!!

@mikehardy
Copy link
Collaborator

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

@abdulghanitech
Copy link

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",

@mikehardy
Copy link
Collaborator

@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?

@christophby
Copy link

christophby commented Aug 28, 2020

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)

@sangameshrently
Copy link

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

@christophby
Copy link

christophby commented Nov 25, 2020

@sangameshrently

Unfortunately I didn't

@Alirez14
Copy link

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)

Same for me here

@janithl
Copy link

janithl commented Feb 2, 2021

*Bump*

Facing same issue on both Android and iOS (and no, removing the filter in the dashboard doesn't help)

"@react-native-firebase/app": "^10.5.0",
"@react-native-firebase/crashlytics": "^10.5.1",
...
"react-native": "0.63.3",

@invertase invertase locked as spam and limited conversation to collaborators Feb 2, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
help: needs-triage Issue needs additional investigation/triaging. platform: ios plugin: crashlytics Firebase Crashlytics type: bug New bug report
Projects
None yet
Development

No branches or pull requests

9 participants