Skip to content

[$250] [Sentry: APP-7CX] HybridApp iOS Fatal App Hang in YAPLJS callFunction during onBarButtonItemSelected (still occurring after #86334 closed) #91229

@mountiny

Description

@mountiny

Sentry

https://expensify.sentry.io/issues/APP-7CX

Impact (snapshot at filing)

  • Users (total since first seen): 3,395
  • Events: 3,627
  • Users (last 14d): ~86
  • First seen: 2026-03-11
  • Last seen: now (ongoing)
  • Platform: iOS, hybrid_app (HybridApp / OldDot)
  • App version(s): 9.3.59 and later (still occurring on 9.3.77)
  • Device class: high (iPhone15+, iOS 26.x dominant)
  • Mechanism: AppHang, fatal, watchdog termination after 2000ms main-thread block

Stack trace (top frames, native iOS)

-[UIControl _sendActionsForEvents:withEvent:]
  → -[UIBarButtonItem _triggerActionForEvent:fallbackSender:]
  → -[BaseViewController onBarButtonItemSelected:]
  → +[YAPLJS callFunction:args:]
  → -[JSValue callWithArguments:]
  → JSObjectCallAsFunction
  → JSC::profiledCall
  → JSC::Interpreter::executeCall
  → (... JS execution ...)
  → +[YAPLLogManager logWithLevel:message:parameters:tags:syncWithServer:isInsecure:]
  → +[YAPLLogManager commitLogLine:...]
  → LogSyncerManager.addLog
  → LogSyncerManager.sendLogPacket
  → +[YAPLJS callFunction:args:]            ← second JS entry from inside the first
  → -[JSValue callWithArguments:]
  → JSC::JSLock::grabAllLocks
  → JSC::JSLock::lock
  → WTF::LockAlgorithm<…>::lockSlow
  → WTF::ParkingLot::parkConditionallyImpl
  → WTF::ThreadCondition::timedWait
  → _pthread_cond_wait                       ← main thread blocked here

Suspected cause

JSC lock contention deadlock. The main thread enters JS through YAPLJS callFunction:args: to handle the bar button tap, the JS handler calls Log (or another function that goes through YAPLLogManager), and LogSyncerManager.sendLogPacket re-enters JSC via a second +[YAPLJS callFunction:args:]. The second entry contends for the JSC lock held by the first entry on the same thread, the parking lot puts the thread to sleep, and the watchdog terminates the app at the 2000ms threshold.

Avoiding re-entrant JSC calls inside LogSyncerManager.sendLogPacket (e.g. by dispatching the second call to a serial queue rather than executing it inline) is the most likely fix direction.

Reproduction

Unknown deterministically. Triggers on bar button taps when the resulting JS handler logs something that causes a re-entrant native-to-JS call.

Related

Two more Sentry groupings hit the same OldDot iOS bar-button-tap path — flagging here so they can be tracked under one fix:

Sentry ID Users (last 14d) Signature
APP-7CX (this issue) ~86 Fatal App Hang +[YAPLJS callFunction:args:]
APP-84S ~20 Same Fatal App Hang +[YAPLJS callFunction:args:] signature
APP-82E ~15 NSRangeException objectAtIndexedSubscript index 0 beyond bounds for empty array at -[BaseViewController onBarButtonItemSelected:] (same culprit frame in this issue's stack)

Same root-cause family as far as the stack shows — recursive JSC invocation triggered from a bar-button tap handler. A fix here should resolve all three.

Upwork Automation - Do Not Edit
Issue OwnerCurrent Issue Owner: @Ollyws

Metadata

Metadata

Labels

BugSomething is broken. Auto assigns a BugZero manager.DailyKSv2ExternalAdded to denote the issue can be worked on by a contributorHelp WantedApply this label when an issue is open to proposals by contributorsOverdue

Type

No type
No fields configured for issues without a type.

Projects

Status

SUBISSUE

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions