Repository navigation
[Sentry: APP-KDF] HybridApp iOS fatal hang — RCTMarkdownUtils applyMarkdownFormatting blocks the main thread in the Yoga measure pass #99849
Description
Activity
- added a parent issue
on Aug 30, 2026 @mountiny Uh oh! This issue is overdue by 2 days. Don't forget to update your issues!
@mountiny Uh oh! This issue is overdue by 2 days. Don't forget to update your issues!
@mountiny Uh oh! This issue is overdue by 2 days. Don't forget to update your issues!
- addedExternalAdded to denote the issue can be worked on by a contributorAdded to denote the issue can be worked on by a contributor
on Sep 3, 2026 Triggered auto assignment to Contributor-plus team member for initial proposal review - @Krishna2323 (
External)Unable to auto-create job on Upwork. The BZ team member should create it manually for this issue.
@Krishna2323 Eep! 4 days overdue now. Issues have feelings too...
@MelvinBot can you check this event in Sentry? Is it still reproducible in the latest versions?
Reacted by melvin-botShort answer: this should already be fixed as of App 9.4.65 — but I could not read Sentry to confirm no new events have landed since. My Sentry connection failed on this run, so everything below is from the code and version history, not from live event data.
What I found
Every affected version in the report (9.4.56-3 → 9.4.60-2) pinned
@expensify/react-native-live-markdownat 0.1.334, which does not contain the fix for this exact hang.The fix is Fix main thread hang on iOS (#772), merged 2026-08-24. It targets precisely the stack in this issue — main thread stuck in
objc_sync_enterinsideapplyMarkdownFormatting:…markdownStyle:parserId:during the Yoga measure pass. Both the lock inversion and the "measure parses synchronously" problem described in the issue body are addressed:- The
@synchronizedblock now covers only the_markdownStyle/_parserIdwrites, so no lock is held across the worklet runtime call (apple/RCTMarkdownUtils.mm:48-51). - On a main-thread cache miss it warms the cache asynchronously and returns instead of entering the runtime (
apple/RCTMarkdownUtils.mm:56-75). - A 4-entry parse cache replaced the single-entry memo, so repeated measures of unchanged text no longer re-enter the parser (
apple/MarkdownParser.mm).
Version chain
live-markdown Has fix? App 9.4.56-3 … 9.4.64-3 0.1.334 ❌ App 9.4.65-0 onward 0.1.336 ✅ App main today (9.4.75-1) 0.1.336 ✅ The bump landed in #99324 (merged 2026-08-29), first shipping in 9.4.65-0.
Note the App-side patch PR referenced from #772 (#97871) was closed unmerged — the fix went upstream into the library instead and reached App via the version bump, so the coverage is real.
What still needs a human
- Filter the Sentry issue to
release >= 9.4.65. If APP-KDF has zero events on 9.4.65+, close it. If events are still arriving on those releases, the fix is incomplete and this needs reopening as a follow-up on Update version to 1.0.1-174 #772. - I did not run a live repro. This is an iOS native watchdog hang; the tester available to me on this run drives web, which cannot reproduce or rule out an Objective-C lock stall on the iOS main thread.
The linked prior-art issue #93831 (APP-EF1) is the same root cause — #772 names it directly — so both should clear together.
Next Steps: Reply with
@MelvinBot <your feedback>to refine this analysis.
- The
@Krishna2323 Still overdue 6 days?! Let's take care of this!
I'll review this today.
@Krishna2323 Whoops! This issue is 2 days overdue. Let's get this updated quick!
@Krishna2323 Eep! 4 days overdue now. Issues have feelings too...
@mountiny Not reproducible on current builds, this is already fixed. All 59 events are on 9.4.64-3 or older, with zero events on 9.4.65+ despite those releases being in the wild (9.4.65-3 has 49 other iOS AppHangs in the last 7d).
Fixed by 982c10c, bumping
@expensify/react-native-live-markdown0.1.334 → 0.1.336, which narrowed the@synchronized (self)block inRCTMarkdownUtils.applyMarkdownFormattingto just the two field assignments and stopped the Yoga measure path from parsing on the main thread. This was the fix for #93831 (APP-EF1), which turns out to be the same root cause as this one, rather than just prior art.Thanks for looking into this, we can close this one then
- removed a parent issue
on Sep 23, 2026
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsDone
Sentry
https://expensify.sentry.io/issues/APP-KDF
Impact (snapshot at filing)
new)AppHang(Fatal App Hang Fully Blocked)-[RCTMarkdownUtils applyMarkdownFormatting:withDefaultTextAttributes:markdownStyle:parserId:]Every affected user in the 14 day window is a new user of this signature, so this is a fresh
regression rather than a long tail.
Stack trace (top frames, main thread)
The event also shows
LiveMarkdownRuntime_queueandLiveMarkdownRuntime(timeout)threads alivewhile the main thread sits in the lock.
Suspected cause
The Yoga measure callback for
MarkdownTextInputDecoratorShadowNodecallsapplyMarkdownFormattingsynchronously on the main thread, and that method blocks on the@synchronizedlock insideRCTMarkdownUtils. The stack shows a very deep layout pass, roughly 100Yoga frames with repeated
layoutAbsoluteDescendantsrecursion, so the measure function is invokedmany times in one pass while the parser lock is held elsewhere. The main thread waits past the two
second watchdog threshold and iOS terminates the app.
Two things worth checking:
applyMarkdownFormattingcan be made lock free on the measure path, or given a cachedmeasurement so repeated measures of unchanged text do not re-enter the parser.
input nested inside several absolutely positioned containers, which multiplies measure calls.
Reproduction
Unknown — see the events linked from the Sentry issue. The affected sample includes iPad on iOS 26.6,
so a large composer with long markdown content is a plausible starting point.
Related
Issue Owner
Current Issue Owner: @Krishna2323