-
Notifications
You must be signed in to change notification settings - Fork 24.4k
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
Symbolicate unhandled promise rejections #40914
Conversation
packages/react-native/Libraries/promiseRejectionTrackingOptions.js
Outdated
Show resolved
Hide resolved
message: {content: warning, substitutions: []}, | ||
isComponentError: false, | ||
codeFrame: stack.codeFrame, | ||
stack: error.stack, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't we just pass the symbolicated stack
variable here instead of the original obfuscated error.stack
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Logbox already supports doing the symbolication, can we leverage the logic there?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you provide more context on how to do that? I can see that he already provided it with the error.stack
but still the correct first frame wasn't shown
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You may need to use LogBox.addException
for this, and update parseLogBoxException
to treat these as non-fatal
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ospfranco can you please give this a try?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pls merge this now 💪 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you try getting rid of the symbolication code in promiseRejectionTrackingOptions
? We should aim to reuse the existing one.
@@ -198,16 +201,17 @@ export function addLog(log: LogData): void { | |||
// otherwise spammy logs would pause rendering. | |||
setImmediate(() => { | |||
try { | |||
const stack = parseErrorStack(errorForStackTrace?.stack); | |||
const defaultStack = parseErrorStack(errorForStackTrace?.stack); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Try this to reuse the same parsing logic for both
const defaultStack = parseErrorStack(errorForStackTrace?.stack); | |
const stack = parseErrorStack(log.stack ?? errorForStackTrace.stack); |
const parseErrorStack = require('./Core/Devtools/parseErrorStack'); | ||
const symbolicateStackTrace = require('./Core/Devtools/symbolicateStackTrace'); | ||
const LogBox = require('./LogBox/LogBox').default; | ||
|
||
const parsedStack = parseErrorStack(error.stack); | ||
|
||
symbolicateStackTrace(parsedStack) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shouldn't live here. Logbox can handle this better by first showing the unsymbolicated stacktrace and then replacing the relevant log when the symbolication is ready.
Which of the existing ones? But now that I got it working I now better why it fails. It's more a question of architecture. Maybe add an extra case in AddException? But which logic should I follow to match the error? |
Logbox will auto-symbolicate the current trace given a valid stack property:
|
yeah, now I got your point @javache. Thanks a lot! |
const parsedStack = parseErrorStack(error.stack); | ||
|
||
LogBox.addLog({ | ||
level: 'warn', | ||
message: {content: warning, substitutions: []}, | ||
componentStack: [], | ||
stack: parsedStack, | ||
category: 'possible_unhandled_promise_rejection', | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we avoid parsing the error stack here, and leave that op to LogBox?
Consider whether addException
may be better here, since it already supports passing in a stack?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just tried but addException tackes an Array<StackFrame>
on the stack
property not a string. Tried modifying that but getting another error:
So it's a chicken and egg problem trying to use that. I can modify addLog to check for a string stack and parsing it there though, would that be a good compromise?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some final nits, but this seems good for merging in.
@@ -10,6 +10,8 @@ | |||
|
|||
import typeof {enable} from 'promise/setimmediate/rejection-tracking'; | |||
|
|||
const LogBox = require('./LogBox/LogBox').default; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use import instead of require here
const warning = | ||
`Possible Unhandled Promise Rejection (id: ${id}):\n` + | ||
`${message ?? ''}\n` + | ||
(stack == null ? '' : stack); | ||
|
||
// Print pretty unhandled rejections while on DEV | ||
if (__DEV__) { | ||
LogBox.addLog({ | ||
level: 'warn', | ||
message: {content: warning, substitutions: []}, | ||
componentStack: [], | ||
stack: error.stack, | ||
category: 'possible_unhandled_promise_rejection', | ||
}); | ||
|
||
return; | ||
} else { | ||
console.warn(warning); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We never write to stack
anymore, can you cleanup warning
?
And I think this will log twice in !__DEV__
(although this module is only ever used if (__DEV__)
, so we could remove this check altogether really.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, reverted the double warning and just handled the special case while on dev
…info if possible (#42079) Summary: This is a continuation of my [last PR](#40914) which improved the symbolication of unhandled promise rejections. While I was developing another library I noticed I still got an error stack of the log adding and not of the error itself. The library I'm trying to debug does not throw a standard error object but rather a custom one, but it still contains the stack field. By passing this stack field to the logbox call I was able to get a better symbolicated stack trace. The exact line of the failure is not displayed but at least the correct file is. ## Changelog: <!-- Help reviewers and the release process by writing your own changelog entry. Pick one each for the category and type tags: [GENERAL] [ADDED] - Unhandled promise rejection - attach non-standard Error object stack info if possible For more details, see: https://reactnative.dev/contributing/changelogs-in-pull-requests Pull Request resolved: #42079 Test Plan: Test any unhandled promise rejection with a non-standard error (line 23, toString must not return `[object Error]`) and see if the correct (or at least a better) stack trace is shown. Here is the one I got before and after this change: <img src="https://github.com/facebook/react-native/assets/1634213/3d07faad-9535-42c9-8032-b4d8fe407e88" width="200" /> <img src="https://github.com/facebook/react-native/assets/1634213/2c39bd82-c7a1-4f58-8ac4-5c479bb96b6e" width="200" /> Reviewed By: huntie Differential Revision: D52431711 Pulled By: cipolleschi fbshipit-source-id: be2172d3b1e2fc3f72812faac372c83bc6dface2
…info if possible (#42079) Summary: This is a continuation of my [last PR](#40914) which improved the symbolication of unhandled promise rejections. While I was developing another library I noticed I still got an error stack of the log adding and not of the error itself. The library I'm trying to debug does not throw a standard error object but rather a custom one, but it still contains the stack field. By passing this stack field to the logbox call I was able to get a better symbolicated stack trace. The exact line of the failure is not displayed but at least the correct file is. ## Changelog: <!-- Help reviewers and the release process by writing your own changelog entry. Pick one each for the category and type tags: [GENERAL] [ADDED] - Unhandled promise rejection - attach non-standard Error object stack info if possible For more details, see: https://reactnative.dev/contributing/changelogs-in-pull-requests Pull Request resolved: #42079 Test Plan: Test any unhandled promise rejection with a non-standard error (line 23, toString must not return `[object Error]`) and see if the correct (or at least a better) stack trace is shown. Here is the one I got before and after this change: <img src="https://github.com/facebook/react-native/assets/1634213/3d07faad-9535-42c9-8032-b4d8fe407e88" width="200" /> <img src="https://github.com/facebook/react-native/assets/1634213/2c39bd82-c7a1-4f58-8ac4-5c479bb96b6e" width="200" /> Reviewed By: huntie Differential Revision: D52431711 Pulled By: cipolleschi fbshipit-source-id: be2172d3b1e2fc3f72812faac372c83bc6dface2
…info if possible (facebook#42079) Summary: This is a continuation of my [last PR](facebook#40914) which improved the symbolication of unhandled promise rejections. While I was developing another library I noticed I still got an error stack of the log adding and not of the error itself. The library I'm trying to debug does not throw a standard error object but rather a custom one, but it still contains the stack field. By passing this stack field to the logbox call I was able to get a better symbolicated stack trace. The exact line of the failure is not displayed but at least the correct file is. ## Changelog: <!-- Help reviewers and the release process by writing your own changelog entry. Pick one each for the category and type tags: [GENERAL] [ADDED] - Unhandled promise rejection - attach non-standard Error object stack info if possible For more details, see: https://reactnative.dev/contributing/changelogs-in-pull-requests Pull Request resolved: facebook#42079 Test Plan: Test any unhandled promise rejection with a non-standard error (line 23, toString must not return `[object Error]`) and see if the correct (or at least a better) stack trace is shown. Here is the one I got before and after this change: <img src="https://github.com/facebook/react-native/assets/1634213/3d07faad-9535-42c9-8032-b4d8fe407e88" width="200" /> <img src="https://github.com/facebook/react-native/assets/1634213/2c39bd82-c7a1-4f58-8ac4-5c479bb96b6e" width="200" /> Reviewed By: huntie Differential Revision: D52431711 Pulled By: cipolleschi fbshipit-source-id: be2172d3b1e2fc3f72812faac372c83bc6dface2
…info if possible (facebook#42079) Summary: This is a continuation of my [last PR](facebook#40914) which improved the symbolication of unhandled promise rejections. While I was developing another library I noticed I still got an error stack of the log adding and not of the error itself. The library I'm trying to debug does not throw a standard error object but rather a custom one, but it still contains the stack field. By passing this stack field to the logbox call I was able to get a better symbolicated stack trace. The exact line of the failure is not displayed but at least the correct file is. ## Changelog: <!-- Help reviewers and the release process by writing your own changelog entry. Pick one each for the category and type tags: [GENERAL] [ADDED] - Unhandled promise rejection - attach non-standard Error object stack info if possible For more details, see: https://reactnative.dev/contributing/changelogs-in-pull-requests Pull Request resolved: facebook#42079 Test Plan: Test any unhandled promise rejection with a non-standard error (line 23, toString must not return `[object Error]`) and see if the correct (or at least a better) stack trace is shown. Here is the one I got before and after this change: <img src="https://github.com/facebook/react-native/assets/1634213/3d07faad-9535-42c9-8032-b4d8fe407e88" width="200" /> <img src="https://github.com/facebook/react-native/assets/1634213/2c39bd82-c7a1-4f58-8ac4-5c479bb96b6e" width="200" /> Reviewed By: huntie Differential Revision: D52431711 Pulled By: cipolleschi fbshipit-source-id: be2172d3b1e2fc3f72812faac372c83bc6dface2
…info if possible (facebook#42079) Summary: This is a continuation of my [last PR](facebook#40914) which improved the symbolication of unhandled promise rejections. While I was developing another library I noticed I still got an error stack of the log adding and not of the error itself. The library I'm trying to debug does not throw a standard error object but rather a custom one, but it still contains the stack field. By passing this stack field to the logbox call I was able to get a better symbolicated stack trace. The exact line of the failure is not displayed but at least the correct file is. ## Changelog: <!-- Help reviewers and the release process by writing your own changelog entry. Pick one each for the category and type tags: [GENERAL] [ADDED] - Unhandled promise rejection - attach non-standard Error object stack info if possible For more details, see: https://reactnative.dev/contributing/changelogs-in-pull-requests Pull Request resolved: facebook#42079 Test Plan: Test any unhandled promise rejection with a non-standard error (line 23, toString must not return `[object Error]`) and see if the correct (or at least a better) stack trace is shown. Here is the one I got before and after this change: <img src="https://github.com/facebook/react-native/assets/1634213/3d07faad-9535-42c9-8032-b4d8fe407e88" width="200" /> <img src="https://github.com/facebook/react-native/assets/1634213/2c39bd82-c7a1-4f58-8ac4-5c479bb96b6e" width="200" /> Reviewed By: huntie Differential Revision: D52431711 Pulled By: cipolleschi fbshipit-source-id: be2172d3b1e2fc3f72812faac372c83bc6dface2
…info if possible (#42079) Summary: This is a continuation of my [last PR](#40914) which improved the symbolication of unhandled promise rejections. While I was developing another library I noticed I still got an error stack of the log adding and not of the error itself. The library I'm trying to debug does not throw a standard error object but rather a custom one, but it still contains the stack field. By passing this stack field to the logbox call I was able to get a better symbolicated stack trace. The exact line of the failure is not displayed but at least the correct file is. ## Changelog: <!-- Help reviewers and the release process by writing your own changelog entry. Pick one each for the category and type tags: [GENERAL] [ADDED] - Unhandled promise rejection - attach non-standard Error object stack info if possible For more details, see: https://reactnative.dev/contributing/changelogs-in-pull-requests Pull Request resolved: #42079 Test Plan: Test any unhandled promise rejection with a non-standard error (line 23, toString must not return `[object Error]`) and see if the correct (or at least a better) stack trace is shown. Here is the one I got before and after this change: <img src="https://github.com/facebook/react-native/assets/1634213/3d07faad-9535-42c9-8032-b4d8fe407e88" width="200" /> <img src="https://github.com/facebook/react-native/assets/1634213/2c39bd82-c7a1-4f58-8ac4-5c479bb96b6e" width="200" /> Reviewed By: huntie Differential Revision: D52431711 Pulled By: cipolleschi fbshipit-source-id: be2172d3b1e2fc3f72812faac372c83bc6dface2
facebook#41377) Summary: For a very long time when a promise rejects without an attached catch we get this warning screen without a correct stack trace, only some internal calls to the RN internals. <img src="https://github.com/facebook/react-native/assets/1634213/75aa7615-ee3e-4229-80d6-1744130de6e5" width="200" /> I created [an issue for discussion](react-native-community/discussions-and-proposals#718) in the react-native-community repo and we figured out it was only a matter of symbolication. While it cannot be done on release without external packages and source maps, at least while developing we can provide a symbolicated stack-trace so developers can better debug the source of rejected promise. I got the stack trace symbolicated and the correct code frame. I'm missing some help trying to display it in the warning view but at the very least I can now correctly show the line of the error and log the codeframe to the console. <!-- Help reviewers and the release process by writing your own changelog entry. Pick one each for the category and type tags: [GENERAL] [FIXED] - Show correct stack frame on unhandled promise rejections on development mode. For more details, see: https://reactnative.dev/contributing/changelogs-in-pull-requests Pull Request resolved: facebook#40914 Test Plan: I simply created a throwing function on a dummy app, and checked the output of the console and the warning view: ```ts import React from 'react'; import {SafeAreaView, Text} from 'react-native'; async function throwme() { throw new Error('UNHANDLED'); } function App(): JSX.Element { throwme(); return ( <SafeAreaView> <Text>Throw test</Text> </SafeAreaView> ); } export default App; ``` Here is the output <img src="https://github.com/facebook/react-native/assets/1634213/2c100e4d-618e-4143-8d64-4095e8370f4f" width="200" /> Edit: I got the warning window working properly: <img src="https://github.com/facebook/react-native/assets/1634213/f02a2568-da3e-4daa-8132-e05cbe591737" width="200" /> Reviewed By: yungsters Differential Revision: D50324344 Pulled By: javache fbshipit-source-id: 66850312d444cf1ae5333b493222ae0868d47056 Co-authored-by: Oscar Franco <[email protected]>
…object stack info if possible (facebook#42079) Summary: This is a continuation of my [last PR](facebook#40914) which improved the symbolication of unhandled promise rejections. While I was developing another library I noticed I still got an error stack of the log adding and not of the error itself. The library I'm trying to debug does not throw a standard error object but rather a custom one, but it still contains the stack field. By passing this stack field to the logbox call I was able to get a better symbolicated stack trace. The exact line of the failure is not displayed but at least the correct file is. <!-- Help reviewers and the release process by writing your own changelog entry. Pick one each for the category and type tags: [GENERAL] [ADDED] - Unhandled promise rejection - attach non-standard Error object stack info if possible For more details, see: https://reactnative.dev/contributing/changelogs-in-pull-requests Pull Request resolved: facebook#42079 Test Plan: Test any unhandled promise rejection with a non-standard error (line 23, toString must not return `[object Error]`) and see if the correct (or at least a better) stack trace is shown. Here is the one I got before and after this change: <img src="https://github.com/facebook/react-native/assets/1634213/3d07faad-9535-42c9-8032-b4d8fe407e88" width="200" /> <img src="https://github.com/facebook/react-native/assets/1634213/2c39bd82-c7a1-4f58-8ac4-5c479bb96b6e" width="200" /> Reviewed By: huntie Differential Revision: D52431711 Pulled By: cipolleschi fbshipit-source-id: be2172d3b1e2fc3f72812faac372c83bc6dface2
Summary:
For a very long time when a promise rejects without an attached catch we get this warning screen without a correct stack trace, only some internal calls to the RN internals.
I created an issue for discussion in the react-native-community repo and we figured out it was only a matter of symbolication. While it cannot be done on release without external packages and source maps, at least while developing we can provide a symbolicated stack-trace so developers can better debug the source of rejected promise.
I got the stack trace symbolicated and the correct code frame. I'm missing some help trying to display it in the warning view but at the very least I can now correctly show the line of the error and log the codeframe to the console.
Changelog:
Test Plan:
I simply created a throwing function on a dummy app, and checked the output of the console and the warning view:
Here is the output
Edit: I got the warning window working properly: