Repository navigation
Large error messages parsed by logbox cause a significant slow down and crash in hermes #32093
Description
Activity
Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as a "Discussion" or add it to the "Backlog" and I will leave it open. Thank you for your contributions.
- addedStaleThere has been a lack of activity on this issue and it may be closed soon.There has been a lack of activity on this issue and it may be closed soon.
on Jan 9, 2022 This issue was closed because it has been stalled for 7 days with no activity.
- locked as resolved and limited conversation to collaborators
on Jan 29, 2022 Thanks for reporting - do you know how large the message needs to be to trigger this? Probably depends on the message?
- unlocked this conversation
on Jun 21, 2023 @rickhanlonii I'm experiencing this issue as well. I'm not sure about the exact size of the message that trigger this. It appears to happen if logging any error with more content than a single stack trace. My case may be different than others however since I json stringify all of my logs for pretty printing in the console. Regardless the issue is still quite a drag on DX.
There's a bit more info in the issue as originally filed on the hermes repo facebook/hermes#581
Reacted by RickyHere's an example of output that crashes the parsing (and hangs the app for 15-20s).
2023-06-21T16:52:20 ERROR: Error building managed_runtime! causePretty: TypeError: Cannot read property '_tag' of undefined at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:140981:21) at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:122238:27) at untraced (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:122272:18) at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:122237:26) at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:140975:27) at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:122182:46) at pipe (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:120606:24) at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:201074:35) at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:122367:26) at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:122371:26) at value (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:146364:26) at _loop2 (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:146598:35) at runLoop (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:146621:28) at _loop (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:146183:40) at evaluateEffect (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:146219:18) at evaluateMessageWhileSuspended (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:146160:34) at drainQueueOnCurrentThread (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:145989:118) at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:145758:40) at starveInternal (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:137918:19) at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:137937:40) at tryCallOne (/Users/distiller/react-native/sdks/hermes/build_iphonesimulator/lib/InternalBytecode/InternalBytecode.js:53:16) at anonymous (/Users/distiller/react-native/sdks/hermes/build_iphonesimulator/lib/InternalBytecode/InternalBytecode.js:139:27) at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:29382:26) at _callTimer (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:29301:17) at _callReactNativeMicrotasksPass (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:29331:17) at callReactNativeMicrotasks (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:29494:44) at __callReactNativeMicrotasks (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:2413:46) at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:2225:45) at __guard (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:2397:15) at flushedQueue (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:2224:21) at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:127593:27) at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:127617:93) at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:127617:59) at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:127335:27) at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:127617:59) defects[1] > message: Cannot read property '_tag' of undefined defects[1] > name: TypeError defects[1] > stack: TypeError: Cannot read property '_tag' of undefined at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:140981:21) at apply (native) at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:122238:27) at untraced (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:122272:18) at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:122237:26) at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:140975:27) at apply (native) at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:122182:46) at pipe (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:120606:24) at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:201074:35) at apply (native) at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:122367:26) at apply (native) at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:122371:26) at value (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:146364:26) at _loop2 (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:146598:35) at runLoop (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:146621:28) at _loop (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:146183:40) at evaluateEffect (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:146219:18) at evaluateMessageWhileSuspended (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:146160:34) at drainQueueOnCurrentThread (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:145989:118) at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:145758:40) at starveInternal (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:137918:19) at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:137937:40) at tryCallOne (/Users/distiller/react-native/sdks/hermes/build_iphonesimulator/lib/InternalBytecode/InternalBytecode.js:53:16) at anonymous (/Users/distiller/react-native/sdks/hermes/build_iphonesimulator/lib/InternalBytecode/InternalBytecode.js:139:27) at apply (native) at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:29382:26) at _callTimer (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:29301:17) at _callReactNativeMicrotasksPass (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:29331:17) at callReactNativeMicrotasks (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:29494:44) at __callReactNativeMicrotasks (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:2413:46) at anonymous (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:2225:45) at __guard (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:2397:15) at flushedQueue (http://192.168.1.84:8081/index.bundle//&platform=ios&dev=true&hot=false:2224:21) ??? > RangeError: An error was thrown when attempting to render log messages via LogBox. ??? > ??? > Maximum regex stack depth reached, js engine: hermesReacted by Ricky@motiz88 @rickhanlonii Thanks for the quick fix! Do you know when this will go out in a react-native release?
@motiz88 @rickhanlonii Thanks for the quick fix! Do you know when this will go out in a react-native release?
It will land in 0.73.
If you wish to have it backported to a previous release, please comment on https://github.com/reactwg/react-native-releases/- added a commit that references this issue
on Jul 3, 2023 - added a commit that references this issue
on Jul 6, 2023 - added a commit that references this issue
on Jul 15, 2023 - added a commit that references this issue
on Aug 23, 2023 Since it's taking a long time for this to get into a release and it completely breaks android dev mode for some people here's a patch you can apply for now
diff --git a/Libraries/LogBox/Data/parseLogBoxLog.js b/Libraries/LogBox/Data/parseLogBoxLog.js index 7b91d697a880e2660aa63a2d0acb58b1f875e84b..4e4cea4f249f109a6b35395aeb08317864b927cd 100644 --- a/Libraries/LogBox/Data/parseLogBoxLog.js +++ b/Libraries/LogBox/Data/parseLogBoxLog.js @@ -14,9 +14,35 @@ import type {LogBoxLogData} from './LogBoxLog'; import parseErrorStack from '../../Core/Devtools/parseErrorStack'; import UTFSequence from '../../UTFSequence'; import stringifySafe from '../../Utilities/stringifySafe'; +import ansiRegex from 'ansi-regex'; + +const ANSI_REGEX = ansiRegex().source; const BABEL_TRANSFORM_ERROR_FORMAT = /^(?:TransformError )?(?:SyntaxError: |ReferenceError: )(.*): (.*) \((\d+):(\d+)\)\n\n([\s\S]+)/; + + +// https://github.com/babel/babel/blob/33dbb85e9e9fe36915273080ecc42aee62ed0ade/packages/babel-code-frame/src/index.ts#L183-L184 +const BABEL_CODE_FRAME_MARKER_PATTERN = new RegExp( + [ + // Beginning of a line (per 'm' flag) + '^', + // Optional ANSI escapes for colors + `(?:${ANSI_REGEX})*`, + // Marker + '>', + // Optional ANSI escapes for colors + `(?:${ANSI_REGEX})*`, + // Left padding for line number + ' +', + // Line number + '[0-9]+', + // Gutter + ' \\|', + ].join(''), + 'm', +); + const BABEL_CODE_FRAME_ERROR_FORMAT = // eslint-disable-next-line no-control-regex /^(?:TransformError )?(?:.*):? (?:.*?)(\/.*): ([\s\S]+?)\n([ >]{2}[\d\s]+ \|[\s\S]+|\u{001b}[\s\S]+)/u; @@ -241,27 +267,31 @@ export function parseLogBoxException( }; } - const babelCodeFrameError = message.match(BABEL_CODE_FRAME_ERROR_FORMAT); + // Perform a cheap match first before trying to parse the full message, which + // can get expensive for arbitrary input. + if (BABEL_CODE_FRAME_MARKER_PATTERN.test(message)) { + const babelCodeFrameError = message.match(BABEL_CODE_FRAME_ERROR_FORMAT); + if (babelCodeFrameError) { + // Codeframe errors are thrown from any use of buildCodeFrameError. + const [fileName, content, codeFrame] = babelCodeFrameError.slice(1); + return { + level: 'syntax', + stack: [], + isComponentError: false, + componentStack: [], + codeFrame: { + fileName, + location: null, // We are not given the location. + content: codeFrame, + }, + message: { + content, + substitutions: [], + }, + category: `${fileName}-${1}-${1}`, + }; + } - if (babelCodeFrameError) { - // Codeframe errors are thrown from any use of buildCodeFrameError. - const [fileName, content, codeFrame] = babelCodeFrameError.slice(1); - return { - level: 'syntax', - stack: [], - isComponentError: false, - componentStack: [], - codeFrame: { - fileName, - location: null, // We are not given the location. - content: codeFrame, - }, - message: { - content, - substitutions: [], - }, - category: `${fileName}-${1}-${1}`, - }; } if (message.match(/^TransformError /)) { diff --git a/package.json b/package.json index fcb222fd4c530ce928dae9ff011caa7bd4703d59..3d2618a5607a40e033cb2a7ad717319c64956384 100644 --- a/package.json +++ b/package.json @@ -90,6 +90,7 @@ "@react-native/virtualized-lists": "^0.72.8", "abort-controller": "^3.0.0", "anser": "^1.4.9", + "ansi-regex": "^5.0.0", "base64-js": "^1.1.2", "deprecated-react-native-prop-types": "4.1.0", "event-target-shim": "^5.0.1",
- added a commit that references this issue
on May 22, 2026
Description
In react native when you log a large error to console.error and logbox attempts to parse it if the message is very large then the following regex throws an exception.
from
node_modules/react-native/Libraries/LogBox/Data/parseLogBoxLog.jsline 251Initially I raised the issue in the hermes repo facebook/hermes#581 and it was suggested to raise it here instead since the regex is seemingly slow and might need some changes.
This starting happening when we recently swapped to hermes on a project where sometimes we get large error messages that return a long graphql query and request body + stack trace. My workaround for now is to just truncate any messages or use a regular log message (not console.error or warn).
React Native version:
Run
react-native infoin your terminal and copy the results here.System:
OS: macOS 10.15.6
CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
Memory: 253.65 MB / 16.00 GB
Shell: 5.7.1 - /bin/zsh
Binaries:
Node: 14.17.0 - /usr/local/opt/node@14/bin/node
Yarn: 1.22.10 - /usr/local/bin/yarn
npm: 6.14.13 - /usr/local/opt/node@14/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
Managers:
CocoaPods: 1.10.1 - /Users/williamsd2/.rvm/gems/ruby-2.7.0/bin/pod
SDKs:
iOS SDK:
Platforms: iOS 14.4, DriverKit 20.2, macOS 11.1, tvOS 14.3, watchOS 7.2
Android SDK: Not Found
IDEs:
Android Studio: 4.2 AI-202.7660.26.42.7351085
Xcode: 12.4/12D4e - /usr/bin/xcodebuild
Languages:
Java: 15.0.2 - /usr/local/opt/openjdk/bin/javac
npmPackages:
@react-native-community/cli: Not Found
react: 17.0.2 => 17.0.2
react-native: 0.65.1 => 0.65.1
react-native-macos: Not Found
npmGlobalPackages:
react-native: Not Found
Steps To Reproduce
I made a minimal repro here https://github.com/dannyhw/hermes-regex-repro
To recreate that you could do the following
npx react-native init repro --template react-native-template-typescriptcode example:
This is the main code in the repro mentioned
Expected Results
Large messages should not crash the app when parsed by logbox.
I think that the regex could maybe be split up to parts to for example not run the regex if the log doesn't contain the initial "TransformError" string at all.
I could work on it if that would be helpful however I would need guidance.
Snack, code example, screenshot, or link to a repository:
I have created a minimal repro here https://github.com/dannyhw/hermes-regex-repro