You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Due for payment 2026-06-12] [$250] [Sentry: APP-8Z0 / APP-8PM] HybridApp iOS EXC_BAD_ACCESS in FullStory native onSessionStarted #91291
Memory access violation inside the FullStory iOS SDK when emitting the session-started event. The crash is fully below our app surface (no first-party frames in the stack), so the underlying fix likely belongs in a FullStory iOS SDK upgrade.
Investigation suggestions
Check what FullStory iOS SDK version we're currently shipping vs the latest release; look for fixes in the changelog around onSessionStarted / fullstoryDidStartSession.
Group by os.version and device.class in Sentry to see if it correlates with iOS 26.x specifically.
As a short-term mitigation, evaluate gating FullStory init on the affected OS / device subset once identified.
Reproduction
Unknown deterministically — fires on any session that reaches FullStory's onSessionStarted callback path. Sentry events are reproducible against the linked sessions in Fullstory dashboard (not pasted here to keep this issue free of identifying data — follow the link in each Sentry event).
Related
Sibling Sentry IDs covered by this issue: APP-8Z0, APP-8PM
Long tail of related single/few-user FullStory native variants: APP-8MH, APP-A78, APP-A35, APP-8WH, APP-9JE (all likely subsumed by the same SDK fix)
The crash occurs in the FullStory native iOS SDK (v1.68.3) during the session-start callback. When FullStory starts a session, fullstoryDidStartSession calls emitOnSessionStarted (a codegen-generated TurboModule EventEmitter method under New Architecture). Inside that emitter, std::__1::__hash_table::__emplace_unique_key_args hits KERN_INVALID_ADDRESS — a use-after-free or uninitialized memory access in the event emitter's internal data structure.
The app has New Architecture enabled (Podfile:82), and the emitOnSessionStarted path is only compiled under RCT_NEW_ARCH_ENABLED. The native iOS SDK v1.68.3 is 3 minor versions behind the latest (1.70.1), and FullStory's release notes for v1.70.0 list two directly relevant fixes:
"Fixed a rare crash that could occur when starting a session"
"Fixed a rare crash associated with objc_retain"
Both match the crash signature (EXC_BAD_ACCESS during session start, memory access violation).
What changes do you think we should make in order to solve the problem?
Upgrade the FullStory native iOS SDK from 1.68.3 to 1.70.1 in ios/Podfile:
- pod 'FullStory', :http => 'https://ios-releases.fullstory.com/fullstory-1.68.3-xcframework.tar.gz'
+ pod 'FullStory', :http => 'https://ios-releases.fullstory.com/fullstory-1.70.1-xcframework.tar.gz'
Then re-run pod install to update Podfile.lock.
What alternative solutions did you explore? (Optional)
Wrapping emitOnSessionStarted in a try/catch or dispatch to main queue — this would require patching @fullstory/react-native source. The crash is inside FullStory's own native code, so an SDK upgrade is the cleaner path.
Gating FullStory init on affected iOS versions — would reduce crash rate but leave the underlying bug in place and degrade FullStory coverage.
Impact context: ~4,625 users affected (74 in last 14 days), iOS 26.x dominant, ongoing since 2026-03-27.
Next Steps for Contributor+ team: Reply with @MelvinBot implement this to create a draft PR, @MelvinBot <your feedback> to refine this analysis, or explain why you are rejecting Melvin's proposal.
Please re-state the problem that we are trying to solve in this issue.
Hybrid iOS builds can crash on the main thread when FullStory starts a native recording session. The crash is affecting production users and the Sentry stack is inside FullStory's session-start callback / React Native session-start event path.
What is the root cause of that problem?
App pins the FullStory native iOS SDK directly in ios/Podfile to https://ios-releases.fullstory.com/fullstory-1.68.3-xcframework.tar.gz, and ios/Podfile.lock confirms the shipped pod is FullStory (1.68.3). Newer FullStory iOS xcframework releases are already available publicly up through 1.70.1, but the app will keep shipping 1.68.3 until that URL and lockfile are updated.
On native, FullstoryInitHandler calls FS.init(userMetadata), which reaches FullStory.restart() once production metadata is available. That is the same session-start path shown in Sentry. Since the crash stack is below our JS/App code in FullStory's native callback dispatch, App-side try/catch or null checks around FS.init will not catch it; we need to move the native FullStory binary off the affected build.
What changes do you think we should make in order to solve the problem?
Update the iOS FullStory pod to the latest available FullStory xcframework release. Concretely, change the direct FullStory pod URL in ios/Podfile from fullstory-1.68.3-xcframework.tar.gz to the latest available release, currently fullstory-1.70.1-xcframework.tar.gz, then regenerate ios/Podfile.lock so the pod version, checkout URL, checksum, and lock metadata all match the new binary. Keep @fullstory/react-native at 1.9.0 unless FullStory publishes a newer React Native wrapper, because npm currently reports 1.9.0 as the latest wrapper version.
If Sentry still shows the same crash after the SDK bump, add a temporary native-only guard in src/libs/Fullstory/index.native.ts / shouldInitializeFullstory to skip FullStory.restart() for the affected iOS version/device cohort while FullStory investigates. That should be treated as a fallback mitigation, not the primary fix, because it disables recording for a subset of users.
Scope boundaries:
Files touched: ios/Podfile - pod 'FullStory' URL; ios/Podfile.lock - regenerated FullStory pod version/source/checksum entries.
Optional fallback only if the SDK bump does not clear Sentry: src/libs/Fullstory/index.native.ts / src/libs/Fullstory/common.ts - native FullStory initialization gate before FullStory.restart().
Platforms: iOS native / HybridApp only.
Code paths not touched: web FullStory (src/libs/Fullstory/index.ts), Android FullStory Gradle plugin, unrelated telemetry integrations, backend/API contracts.
API contracts or backend behavior changes: no.
What alternative solutions did you explore? (Optional)
Only wrapping FS.init, FullStory.restart(), or getSessionURL() in additional JS error handling would not address this crash because the fatal fault occurs later inside the native FullStory SDK callback path. Permanently disabling FullStory on iOS would stop the crash, but it is broader than needed and loses session replay for all iOS users; it should only be used as a short-term cohort-specific mitigation if the SDK upgrade is not sufficient.
The crashing frames -[FullStory fullstoryDidStartSession:] → -[NativeFullStorySpecBase emitOnSessionStarted:] are not in the native FullStory xcframework — they are in the @fullstory/react-native bridge module, which is already on the latest npm release (1.9.0).
The module registers itself as FullStory's delegate exactly once, in -init, and never clears it — there is no dealloc or invalidate anywhere in the implementation:
- (instancetype)init {
self = [superinit];
if (self) {
FS.delegate = self; // set once, never reset
...
So it is not a zeroing weak reference — when the module instance is freed, FS keeps pointing at the dead object. Under New Architecture, the session-start callback then invokes the codegen event emitter:
- (void) fullstoryDidStartSession:(NSString *)sessionUrl {
...
#ifdef RCT_NEW_ARCH_ENABLED
[selfemitOnSessionStarted:@{ ... }]; // std::function bound to this module's runtime/CallInvoker
#endif
}
The FS SDK is an app-lifetime singleton, but in HybridApp the React Native instance is created and destroyed across OldDot↔NewDot transitions. When FS starts a session after the RN instance that owned this module has been torn down, the never-cleared, non-weak FS.delegate fires fullstoryDidStartSession: into a module whose runtime / emitter storage is already freed. The event emitter's std::function then dereferences freed memory inside __hash_table::__emplace_unique_key_args → KERN_INVALID_ADDRESS (EXC_BAD_ACCESS) — exactly the reported stack. This is why the crash is hybrid_app-only: a standalone NewDot app has one long-lived RN instance, so the dangling-delegate window barely exists.
What changes do you think we should make in order to solve the problem?
Stop a torn-down module from receiving the native callback by clearing the delegate when it goes away — patching @fullstory/react-native/ios/FullStory.mm via patch-package (new file patches/@fullstory+react-native+1.9.0.patch):
- (instancetype)init {
self = [super init];
if (self) {
FS.delegate = self;
onReadyPromises = [NSMutableArray new];
}
return self;
}
++ - (void)dealloc {+ // FS.delegate is a non-weak class property on an app-lifetime singleton.+ // Clear it when this RN module is freed so a session-started callback can't+ // fire into a torn-down runtime (HybridApp OldDot<->NewDot transitions).+ if (FS.delegate == self) {+ FS.delegate = nil;+ }+ }
The if (FS.delegate == self) guard is important: when a new RN instance spins up it overwrites FS.delegate in its own -init, so a late-deallocating old instance must not clobber the live registration.
For extra determinism I'd also conform the module to RCTInvalidating and run the same clear in -invalidate, which fires on RN-instance teardown before dealloc.
This lives in the JS package, so it is picked up by every iOS build that consumes @fullstory/react-native (including the HybridApp build that bundles the App's node_modules), and it doesn't depend on a third-party release-note guess.
What alternative solutions did you explore? (Optional)
Upgrade the native FullStory xcframework (ios/Podfile L126, currently 1.68.3). FullStory 1.70.0 release notes do mention a session-start crash fix, so this may help as a complementary measure. I rejected it as the primary fix because (a) it gambles that the release-note line covers this exact New-Arch emit path — the crashing code is in the RN bridge, which the xcframework bump doesn't touch; and (b) the crash is on HybridApp builds, whose iOS binary is built from the Mobile-Expensify submodule, not App's ios/ project — so a App/ios/Podfile-only bump updates just the standalone NewDot iOS dev build and would not ship to the crashing builds unless the same pin is updated wherever HybridApp resolves FullStory.
Gate FullStory init on the affected OS/device subset — lowers the crash rate but leaves the dangling delegate in place and degrades FullStory coverage. Rejected.
[Contributor] The offending PR and associated issue have been commented on, pointing out the bug it caused and why, so the author and reviewers can learn from the mistake.
N/A - we bumped libs versions here
[Contributor] If the regression was CRITICAL (e.g. interrupts a core flow) A discussion in #expensify-open-source has been started about whether any other steps should be taken (e.g. updating the PR review checklist) in order to catch this type of bug sooner.
Link to discussion: N/A
[Contributor] If it was decided to create a regression test for the bug, please propose the regression test steps using the template below to ensure the same bug will not reach production again.
@Eskalifer1 can you please accept the job below? Please reply here and tag me once you have.
If you're not sent an offer in Upwork when you're assigned to an issue, please tag me. If an Upwork job exists, please submit a proposal. https://www.upwork.com/jobs/~022057428000347458847
Activity
[-][Sentry: APP-8Z0 / APP-8PM] HybridApp iOS EXC_BAD_ACCESS in FullStory native onSessionStarted (~4.6k users)[/-][+][Sentry: APP-8Z0 / APP-8PM] HybridApp iOS EXC_BAD_ACCESS in FullStory native onSessionStarted [/+]MelvinBot commentedon May 21, 2026
Proposal
What is the root cause of that problem?
The crash occurs in the FullStory native iOS SDK (v1.68.3) during the session-start callback. When FullStory starts a session,
fullstoryDidStartSessioncallsemitOnSessionStarted(a codegen-generated TurboModule EventEmitter method under New Architecture). Inside that emitter,std::__1::__hash_table::__emplace_unique_key_argshitsKERN_INVALID_ADDRESS— a use-after-free or uninitialized memory access in the event emitter's internal data structure.The app has New Architecture enabled (
Podfile:82), and theemitOnSessionStartedpath is only compiled underRCT_NEW_ARCH_ENABLED. The native iOS SDK v1.68.3 is 3 minor versions behind the latest (1.70.1), and FullStory's release notes for v1.70.0 list two directly relevant fixes:Both match the crash signature (EXC_BAD_ACCESS during session start, memory access violation).
What changes do you think we should make in order to solve the problem?
Upgrade the FullStory native iOS SDK from 1.68.3 to 1.70.1 in
ios/Podfile:Then re-run
pod installto updatePodfile.lock.What alternative solutions did you explore? (Optional)
emitOnSessionStartedin a try/catch or dispatch to main queue — this would require patching@fullstory/react-nativesource. The crash is inside FullStory's own native code, so an SDK upgrade is the cleaner path.Investigation details
Data flow to crash:
FS.delegate = selfduring initFullstoryInitHandlermounts → callsconsentAndIdentify()→FullStory.restart()fullstoryDidStartSessiondelegate callbackemitOnSessionStarted(New Arch EventEmitter codegen) outside the@synchronizedblock__hash_table::__emplace_unique_key_args→KERN_INVALID_ADDRESSKey files:
ios/Podfile:126— native SDK version pinpackage.json:93—@fullstory/react-nativev1.9.0 (latest, no upgrade needed)src/libs/Fullstory/index.native.ts— init/consent flowsrc/FullstoryInitHandler.tsx— triggersFS.init()Impact context: ~4,625 users affected (74 in last 14 days), iOS 26.x dominant, ongoing since 2026-03-27.
Next Steps for Contributor+ team: Reply with
@MelvinBot implement thisto create a draft PR,@MelvinBot <your feedback>to refine this analysis, or explain why you are rejecting Melvin's proposal.melvin-bot commentedon May 21, 2026
Triggered auto assignment to Contributor-plus team member for initial proposal review - @Eskalifer1 (
External)[-][Sentry: APP-8Z0 / APP-8PM] HybridApp iOS EXC_BAD_ACCESS in FullStory native onSessionStarted [/-][+][$250] [Sentry: APP-8Z0 / APP-8PM] HybridApp iOS EXC_BAD_ACCESS in FullStory native onSessionStarted [/+]melvin-bot commentedon May 21, 2026
Job added to Upwork: https://www.upwork.com/jobs/~022057428000347458847
KJ21-ENG commentedon May 21, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
Hybrid iOS builds can crash on the main thread when FullStory starts a native recording session. The crash is affecting production users and the Sentry stack is inside FullStory's session-start callback / React Native session-start event path.
What is the root cause of that problem?
App pins the FullStory native iOS SDK directly in ios/Podfile to https://ios-releases.fullstory.com/fullstory-1.68.3-xcframework.tar.gz, and ios/Podfile.lock confirms the shipped pod is FullStory (1.68.3). Newer FullStory iOS xcframework releases are already available publicly up through 1.70.1, but the app will keep shipping 1.68.3 until that URL and lockfile are updated.
On native, FullstoryInitHandler calls FS.init(userMetadata), which reaches FullStory.restart() once production metadata is available. That is the same session-start path shown in Sentry. Since the crash stack is below our JS/App code in FullStory's native callback dispatch, App-side try/catch or null checks around FS.init will not catch it; we need to move the native FullStory binary off the affected build.
What changes do you think we should make in order to solve the problem?
Update the iOS FullStory pod to the latest available FullStory xcframework release. Concretely, change the direct FullStory pod URL in ios/Podfile from fullstory-1.68.3-xcframework.tar.gz to the latest available release, currently fullstory-1.70.1-xcframework.tar.gz, then regenerate ios/Podfile.lock so the pod version, checkout URL, checksum, and lock metadata all match the new binary. Keep @fullstory/react-native at 1.9.0 unless FullStory publishes a newer React Native wrapper, because npm currently reports 1.9.0 as the latest wrapper version.
If Sentry still shows the same crash after the SDK bump, add a temporary native-only guard in src/libs/Fullstory/index.native.ts / shouldInitializeFullstory to skip FullStory.restart() for the affected iOS version/device cohort while FullStory investigates. That should be treated as a fallback mitigation, not the primary fix, because it disables recording for a subset of users.
Scope boundaries:
What alternative solutions did you explore? (Optional)
Only wrapping FS.init, FullStory.restart(), or getSessionURL() in additional JS error handling would not address this crash because the fatal fault occurs later inside the native FullStory SDK callback path. Permanently disabling FullStory on iOS would stop the crash, but it is broader than needed and loses session replay for all iOS users; it should only be used as a short-term cohort-specific mitigation if the SDK upgrade is not sufficient.
yusufdeveloper2903 commentedon May 21, 2026
Proposal
What is the root cause of that problem?
The crashing frames
-[FullStory fullstoryDidStartSession:]→-[NativeFullStorySpecBase emitOnSessionStarted:]are not in the native FullStory xcframework — they are in the@fullstory/react-nativebridge module, which is already on the latest npm release (1.9.0).The module registers itself as FullStory's delegate exactly once, in
-init, and never clears it — there is nodeallocorinvalidateanywhere in the implementation:FullStory.mmL16-L23FS.delegateis a class property declared withoutweak(FullStory.framework/Headers/FS.h):@property (class) id<FSDelegate> _Nullable delegate;So it is not a zeroing weak reference — when the module instance is freed,
FSkeeps pointing at the dead object. Under New Architecture, the session-start callback then invokes the codegen event emitter:FullStory.mmL197-L209The
FSSDK is an app-lifetime singleton, but in HybridApp the React Native instance is created and destroyed across OldDot↔NewDot transitions. WhenFSstarts a session after the RN instance that owned this module has been torn down, the never-cleared, non-weakFS.delegatefiresfullstoryDidStartSession:into a module whose runtime / emitter storage is already freed. The event emitter'sstd::functionthen dereferences freed memory inside__hash_table::__emplace_unique_key_args→KERN_INVALID_ADDRESS (EXC_BAD_ACCESS)— exactly the reported stack. This is why the crash ishybrid_app-only: a standalone NewDot app has one long-lived RN instance, so the dangling-delegate window barely exists.What changes do you think we should make in order to solve the problem?
Stop a torn-down module from receiving the native callback by clearing the delegate when it goes away — patching
@fullstory/react-native/ios/FullStory.mmviapatch-package(new filepatches/@fullstory+react-native+1.9.0.patch):- (instancetype)init { self = [super init]; if (self) { FS.delegate = self; onReadyPromises = [NSMutableArray new]; } return self; } + + - (void)dealloc { + // FS.delegate is a non-weak class property on an app-lifetime singleton. + // Clear it when this RN module is freed so a session-started callback can't + // fire into a torn-down runtime (HybridApp OldDot<->NewDot transitions). + if (FS.delegate == self) { + FS.delegate = nil; + } + }The
if (FS.delegate == self)guard is important: when a new RN instance spins up it overwritesFS.delegatein its own-init, so a late-deallocating old instance must not clobber the live registration.For extra determinism I'd also conform the module to
RCTInvalidatingand run the same clear in-invalidate, which fires on RN-instance teardown beforedealloc.This lives in the JS package, so it is picked up by every iOS build that consumes
@fullstory/react-native(including the HybridApp build that bundles the App'snode_modules), and it doesn't depend on a third-party release-note guess.What alternative solutions did you explore? (Optional)
ios/PodfileL126, currently1.68.3). FullStory 1.70.0 release notes do mention a session-start crash fix, so this may help as a complementary measure. I rejected it as the primary fix because (a) it gambles that the release-note line covers this exact New-Arch emit path — the crashing code is in the RN bridge, which the xcframework bump doesn't touch; and (b) the crash is on HybridApp builds, whose iOS binary is built from the Mobile-Expensify submodule, not App'sios/project — so aApp/ios/Podfile-only bump updates just the standalone NewDot iOS dev build and would not ship to the crashing builds unless the same pin is updated wherever HybridApp resolves FullStory.32 remaining items
melvin-bot commentedon Jun 11, 2026
Triggered auto assignment to @mallenexpensify (
Awaiting Payment)melvin-bot commentedon Jun 11, 2026
Payment Summary
Upwork Job
BugZero Checklist (@mallenexpensify)
Eskalifer1 commentedon Jun 15, 2026
BugZero Checklist:
[Contributor] The offending PR and associated issue have been commented on, pointing out the bug it caused and why, so the author and reviewers can learn from the mistake.
N/A - we bumped libs versions here
[Contributor] If the regression was CRITICAL (e.g. interrupts a core flow) A discussion in #expensify-open-source has been started about whether any other steps should be taken (e.g. updating the PR review checklist) in order to catch this type of bug sooner.
Link to discussion: N/A
[Contributor] If it was decided to create a regression test for the bug, please propose the regression test steps using the template below to ensure the same bug will not reach production again.
N/A - we bumped libs versions here
mallenexpensify commentedon Jun 15, 2026
Payment Summary
Contributor+: @Eskalifer1 paid $250 via Upwork.
@Eskalifer1 can you please accept the job below? Please reply here and tag me once you have.
If you're not sent an offer in Upwork when you're assigned to an issue, please tag me. If an Upwork job exists, please submit a proposal.
https://www.upwork.com/jobs/~022057428000347458847
Eskalifer1 commentedon Jun 15, 2026
Hi @mallenexpensify, sure, i have accepted, thank you!
mallenexpensify commentedon Jun 15, 2026
@Eskalifer1 paid, summary updated above. Thx.