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
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
#### `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
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`
React Native Firebase
and Invertase
on Twitter for updates on the library.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.
@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
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.