Closed thomasblom closed 4 years ago
Did you keep the sourcemap for your bundle build? Or tag the source so you could regenerate it at that point in time and de-obfuscate? You'll need to map it back in order to get the stack trace you want. None of the crash services that I'm aware of handle react-native / javascript bundle de-obfuscation automatically
I had same problem, trying to de-obfuscate. In this SO post, check the answer that helped us de-obfuscate ios crashlytics logs.
Thanks for a quick reply guys! I understand we can de-obfuscate with the sourcemap of our bundle build. The struggle we have is more about the Firebase Crashlytics overview, which will only show index.android/ios.bundle
. So we cannot see any difference between two logs, except the line numbers. But there is nothing to do about this, am i correct @mikehardy?
@angelos3lex thanks for the tip! But stack-beautifier
doesn't understand the stacktrace which Firebase Crashlytics gives me. Do you know what i'm doing wrong?
The package refers to the error here, but I think this is a valid format.
Thanks in advance.
@thomasblom add new line before each at ...
i.e:
Non-fatal Exception: io.invertase.firebase.crashlytics.JavaScriptError: TEST
at .(index.android.bundle:1221:2263)
at .p(index.android.bundle:113:423)
at .(index.android.bundle:113:1724)
(No need to add all these lines, the first 4-5 at ...
lines will most probably be adequate for tracking down the crash, or at least to check for the test)
@angelos3lex Sorry, my previous comment wasn't formatted the right way. I already had new lines (see my edited comment), still getting errors like this:
/usr/local/lib/node_modules/stack-beautifier/stack-beautifier.js:123
throw new Error(`Stack trace parse error at line ${i + 1}: ${line}`);
^
Error: Stack trace parse error at line 2: at .(index.android.bundle:1221:2263)
Do you have any ideas?
@thomasblom I'm not sure, because on firebase console, my trace was like this:
Unhandled JS Exception: Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undef..., stack:
Ol@161:86813
<unknown>@161:39525
Hr@161:48370
Cl@161:82658
and then, the outcome of the beautifier was the lines with at ...
but each at ...
had the actual function name in a normal readable format. So your stack trace seems a little bit different. :( Maybe this is a difference between ios and android obfuscation, and any further step is needed or smthing?!
@angelos3lex It works with a trace like yours, but of course not the right files/lines. It's weird the package says it supports the format of my stacktrace, but it doesn't. I will look into this. Thanks anyway for your help!
@mikehardy Do you know how I can get JSC stack traces instead of the format i'm getting?
I do not, sorry. I log synthetic analytics "screen" events via react-navigation on each navigation change (the typical pattern to work around react-native using only a single activity) and typically some other data related to session state. That in combination with even objectively terrible stack traces like the above, has been enough for me to quickly inspect code and see the problem in practice so I haven't dug deeper
Feel free to continue the discussion but this isn't an issue with React Native Firebase, so I'm going to go ahead and close it.
Got such error in firebase Console
Yeah, I have my first live build out with the with the v8 crashlytics and I see similar on the java side @Daha62 so I can confirm that Firebase Crashlytics (the thing we just migrated to) can generate stacks like this. Why? I'm unsure in my case. I need to verify if I'm actually uploading the deobfuscation files (I may not be) etc.
Can you verify if you have sent all the de-obfuscation files up to firebase etc?
I think this has to do with your project-specific environments. I'm on the move right now so I can't provide a proper screenshot, but my V8 test crash stack trace is fine:
Fatal Exception: java.lang.RuntimeException: Crash Test
at io.invertase.firebase.crashlytics.ReactNativeFirebaseCrashlyticsModule$1.run(ReactNativeFirebaseCrashlyticsModule.java:45)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run(MessageQueueThreadImpl.java:225)
at java.lang.Thread.run(Thread.java:764)
Great, thanks for the success report @andersonaddo I was pretty sure it was my local project, now I know to really focus on that
Hi, will any update for this issue? or this issue has been closed permanently?
I also find my stacktraces is difficult to analyze?
"@react-native-firebase/analytics": "^6.4.0",
"@react-native-firebase/app": "^6.4.0",
"@react-native-firebase/crashlytics": "^6.4.0",
"@react-native-firebase/dynamic-links": "^6.4.0",
"@react-native-firebase/messaging": "^6.4.0",
"@react-native-firebase/perf": "^6.4.0",
"@react-native-firebase/remote-config": "^6.4.0",
Android
iOS
@abdullahizzuddiin Firebase Crashlytics knows nothing of javascript stack traces. You will need to post-process javascript stack traces https://stackoverflow.com/questions/62214336/react-native-firebase-crashlytics-deobfuscation/62300702#62300702 was posted above and I think it's useful
There is hope perhaps, it appears that firebase crashlytics has added some ability to add information to stack frames manually which would mean it is maybe possible to construct more informative stack traces from the javascript code https://github.com/firebase/firebase-ios-sdk/issues/5975 - not sure exactly how useful it would be but if someone was interested in advancing this area we could certainly merge related PRs...
Awesome!
stack-beautifier lib worked beautifully on my Android Stacktrace.
But, is there a way to separate issues based on stacktraces?
Look at this pic,
So many difference crashes is grouped together on ExceptionsManagerModule.java – line 71: com.facebook.react.modules.core.ExceptionsManagerModule.reportException
issue. If we look at the detail, we will find many difference stacktraces (means difference bugs) collected there.
I am happy stack-beautifier worked for you! I am not aware of away to differentiate higher layers of the stack though unfortunately, for the same reason you have to post-process javascript stacks, Firebase simply does not know about differences that are higher than the native layer, yet
There is potential to pass this information to firebase with the APIs I linked above but we don't have that feature now, and it is not under development by us or anyone proposing a PR yet that I know about
Strangely the custom stack traces thing does not appear available on Android. On iOS it was added in pod 6.21.0
Hi @thomasblom did you solve the problem you were facing? I'm having the same issue.
Ok, so i went through the source code of stack-beautifier.
The regex relevant to the format returned by Crashlytics is as follows.
/^at (.*) \((.*)\:(\d+)\:(\d+)\)$/
For those of us who are using crashlytics on android will get the stack trace as txt in the below format:
Non-fatal Exception: io.invertase.firebase.crashlytics.UnhandledPromiseRejection: undefined is not an object (evaluating 'c.bodyString')
at .<unknown>(index.android.bundle:1730:1890)
at .p(index.android.bundle:79:423)
We need to pre-process the crashlytics trace file for stack-beautifier to parse it properly. I created a shell script to do this. Save the below code in a file called preprocess.sh
sed -i 's/\s*at/at/g' $1
sed -i 's/(/ (/g' $1
sed -i 's/:0:/:1:/g' $1 # Stack beautifier indexes lines from 1 and not 0
Run this script
bash preprocess.sh <stack trace filename>
Now, we just have to run stack-beautifier.
stack-beautifier <map file name> -t <stack trace filename>
Hope this helps someone in the future.
@thomasblom
Paring down my stack trace text to the first two lines, and adding a space after the stack trace function and before the opening parentheses fixed my stack-beautifier Stack trace parse error.
File: mytrace.txt
# stack trace text copied from crashlytics after deleting all but first two lines
Non-fatal Exception: io.invertase.firebase.crashlytics.UnhandledPromiseRejection: undefined is not an object (evaluating 't.includes')
at .removeFile(index.android.bundle:474:6500)
# Inserted a space after the 'removeFile' function and before opening '('
# fixed the stack-beautifier "Stack trace parse error"
Non-fatal Exception: io.invertase.firebase.crashlytics.UnhandledPromiseRejection: undefined is not an object (evaluating 't.includes')
at .removeFile (index.android.bundle:474:6500)
Success!
Found the origination of my removeFile function error in source file Utility.js:567:17
stack-beautifier sourcemap.android.js -t mytrace.txt
Non-fatal Exception: io.invertase.firebase.crashlytics.UnhandledPromiseRejection: undefined is not an object (evaluating 't.includes')
at includes (/Users/eddie/Documents/projects/react-native/myapp/v1.6.1146/source/app/components/Utility.js:567:17)
Also, stack-beautifier seems to crash when it encounters [native code] in the trace. I deleted all trace lines starting at first [native code] line.
# Delete all stack trace lines startign at first found line containing [native code]
at .callImmediates ([native code]:0:0)
If this is something we could alter here without affecting backwards compatibility we could take a PR for it We're in control of this stack trace generation here:
(and in native android as example, perhaps this is the root of formatting issues as this appears to be the standard for Java error reporting at least based on native experience)
We are using stacktrace-js though - odd that it is somehow not compatible out of the box with stack-beautifier :thinking: ?
Perhaps if you tried stacktrace-gps instead https://www.stacktracejs.com/#!/docs/stacktrace-gps ?
@mikehardy thank you for your crashlytics work!
I will happily use any stack trace tool that can associate crashlytics stack trace text with the react native android or ios sourcemap files. Crashlytics is great at notifying me when something is going wrong with my react native apps. However, the stack trace text seldom leads me to the offending source code line.
I am struggling to understand how to use stacktrace-js or stacktrace-gps with a react native sourcemap and crashlytics stack trace text.
This is what I tried. I get "StackFrame is not defined".
File: stacktrace-gps-test.js
// Added local sourcemap file, line and column
var stackframe = new StackFrame({fileName: 'sourcemap.android.js', lineNumber: 474, columnNumber: 6500});
var callback = function myCallback(foundFunctionName) { console.log(foundFunctionName); };
// Such meta. Wow var errback = function myErrback(error) { console.log(StackTrace.fromError(error)); };
var gps = new StackTraceGPS();
// Pinpoint actual function name and source-mapped location gps.pinpoint(stackframe).then(callback, errback); //===> Promise(StackFrame({functionName: 'fun', fileName: 'file.js', lineNumber: 203, columnNumber: 9}), Error)
// Better location/name information from source maps gps.getMappedLocation(stackframe).then(callback, errback); //===> Promise(StackFrame({fileName: 'file.js', lineNumber: 203, columnNumber: 9}), Error)
// Get function name from location information gps.findFunctionName(stackframe).then(callback, errback); //===> Promise(StackFrame({functionName: 'fun', fileName: 'http://localhost:3000/file.min.js', lineNumber: 1, columnNumber: 3284}), Error)
Launch from macOS terminal as:
node stacktrace-gps-test.js /Users/edward3/Documents/projects/react-native/field-scout/v1.6.1146/source/stacktrace-gps-test.js:15 var stackframe = new StackFrame({fileName: 'sourcemap.android.js', lineNumber: 474, columnNumber: 6500}); ^
ReferenceError: StackFrame is not defined
at Object.
Is stacktrace-js or stacktrace-gps only usable for traditional node.js apps or browser and not usable for react native apps?
Honestly I don't know :sweat_smile: - I have not tried them locally, I was just trying to provide brainstorming suggestions based on the context I have. It's all a bit of a science fair project in this area (decode of JS minified+etc stack traces) and I haven't seen anything yet that is quite ready for systemitization except maybe the script chunks above (those do look promising)
Confounding it is that I think with Hermes this will get even more difficult to resolve back to source lines
@mikehardy thanks for the input. Any kind of brainstorming is good to help cut through the noise.
This seems to work for me if I remove all stack trace lines starting with first line containing "[native code]"
npx metro-symbolicate sourcemap.android.js < bug-android-stack-trace.txt
npx metro-symbolicate sourcemap.ios.js < bug-ios-stack-trace.txt
preprocess.sh
You save my time!
Documentation Feedback
I have successfully integrated Firebase Crashlytics within my app, but one thing disturbs me. If you look at the results in the Firebase Console, you see a non-fatal error that I logged.
But what I couldn't find in the documentation is how to modify this. Because every error that I will log will come from
io.invertase.firebase.crashlytics.JavaScriptError
In the main overview page with all the errors, you see even less data. All you see is
index.android.bundle
and a minified function where the error came from (.v
). And if it came from an anonymous function, the method is simply.<unknown>
.Is it possible to change these values of the error log? Especially in the main view this is needed, because you won't see the difference between the errors if all you see is a minified function with
index.android.bundle
.Thanks in advance.
React Native Firebase
andInvertase
on Twitter for updates on the library.