Crash in IterableEmbeddedManager.reset() after OTA reload when built with Xcode 26
Environment
-
React Native SDK: @iterable/react-native-sdk
- Reproduced on
2.0.4 (Iterable iOS SDK 6.5.4.1)
- Reproduced on
2.2.2 (Iterable iOS SDK 6.6.7)
-
Platform: iOS (React Native / Expo)
-
iOS Versions: Reproduced on iOS 18 and iOS 26.5
-
Build Toolchain: Xcode 26 (macOS 26.2)
Reproducibility
Reproducible on first OTA transition after fresh install or build upgrade. Subsequent OTA applications on the same binary do not crash.
Summary
When an OTA update is applied via expo-updates, the new JavaScript bundle is loaded into the existing native process. Any call path that triggers:
logoutPreviousUser()
-> IterableEmbeddedManager.reset()
results in:
EXC_BAD_ACCESS (SIGSEGV)
address: 0x00000000000000af
The crash appears only when the app is built with Xcode 26. The same Iterable SDK versions built with an older Xcode toolchain do not exhibit this behavior.
Crash Chain
ReactIterableAPI.set(email:authToken:) ← JS bridge call
IterableAPI.setEmail(_:_:_:_:)
InternalIterableAPI.setEmail(...)
InternalIterableAPI.logoutPreviousUser() ← InternalIterableAPI.swift:572
IterableEmbeddedManager.reset() ← IterableEmbeddedManager.swift:82
→ EXC_BAD_ACCESS (SIGSEGV)
address: 0x00000000000000af
A secondary crash path is also observed:
ErrorRecovery.startPipeline(withEncounteredError:)
ErrorRecovery.waitForRemoteLoaderToFinish() → timeout
ErrorRecovery.crash()
StartupProcedure.throwException(_:) → SIGABRT
Root Cause Hypothesis
The crash appears to be related to dispatch through a Swift protocol witness table associated with IterableEmbeddedUpdateDelegate.
During IterableEmbeddedManager.reset(), execution eventually reaches delegate notification/message update logic. A dispatch through the witness table dereferences a pointer at offset 175 (0xaf), resulting in EXC_BAD_ACCESS.
Observations:
- Reproduces only in binaries compiled with Xcode 26
- Reproduces across multiple Iterable SDK versions (
6.5.4.1 and 6.6.7)
- Does not reproduce when the same SDK version is compiled with an older Xcode toolchain
- Only occurs after an OTA reload, where the native module survives while the JS runtime is restarted
- Does not occur on a cold start, where the native module is initialized from scratch
Because of this, the issue appears to be related either to:
- A Xcode 26 compiler/runtime compatibility issue, or
- A latent lifecycle issue in the SDK that becomes exposed by Xcode 26 code generation and OTA reload behavior
Workarounds Attempted
None of the following prevented the crash:
-
Patching notifyUpdateDelegates() to a no-op
- Crash shifts to
setMessages()
-
Patching IterableEmbeddedManager.reset() to a no-op
- Crash continues elsewhere in the same call chain
-
Skipping IterableAPI.setEmail() and Iterable.initialize() from JavaScript
- Crash still occurs before JS-level guards can prevent execution
Reproduction Steps
- Have app installed from a previous build (or fresh install)
- Install new binary built with Xcode 26
- Open app — first OTA is applied
- Crash occurs
Additional Observation
If the app is launched in airplane mode (preventing the OTA update from being applied), the crash does not occur.
Request
Has the Iterable iOS SDK been validated against Xcode 26 in scenarios where the host application performs runtime reloads (e.g. Expo OTA updates)?
Any guidance, fixes, or builds verified against Xcode 26 would be appreciated. In particular, we'd like to understand whether there are known issues involving:
IterableEmbeddedManager.reset()
IterableEmbeddedUpdateDelegate
- OTA/runtime reload workflows where the native process remains alive while the JS runtime restarts
Crash in
IterableEmbeddedManager.reset()after OTA reload when built with Xcode 26Environment
React Native SDK:
@iterable/react-native-sdk2.0.4(Iterable iOS SDK6.5.4.1)2.2.2(Iterable iOS SDK6.6.7)Platform: iOS (React Native / Expo)
iOS Versions: Reproduced on iOS 18 and iOS 26.5
Build Toolchain: Xcode 26 (macOS 26.2)
Reproducibility
Reproducible on first OTA transition after fresh install or build upgrade. Subsequent OTA applications on the same binary do not crash.
Summary
When an OTA update is applied via
expo-updates, the new JavaScript bundle is loaded into the existing native process. Any call path that triggers:results in:
The crash appears only when the app is built with Xcode 26. The same Iterable SDK versions built with an older Xcode toolchain do not exhibit this behavior.
Crash Chain
A secondary crash path is also observed:
Root Cause Hypothesis
The crash appears to be related to dispatch through a Swift protocol witness table associated with
IterableEmbeddedUpdateDelegate.During
IterableEmbeddedManager.reset(), execution eventually reaches delegate notification/message update logic. A dispatch through the witness table dereferences a pointer at offset175 (0xaf), resulting inEXC_BAD_ACCESS.Observations:
6.5.4.1and6.6.7)Because of this, the issue appears to be related either to:
Workarounds Attempted
None of the following prevented the crash:
Patching
notifyUpdateDelegates()to a no-opsetMessages()Patching
IterableEmbeddedManager.reset()to a no-opSkipping
IterableAPI.setEmail()andIterable.initialize()from JavaScriptReproduction Steps
Additional Observation
If the app is launched in airplane mode (preventing the OTA update from being applied), the crash does not occur.
Request
Has the Iterable iOS SDK been validated against Xcode 26 in scenarios where the host application performs runtime reloads (e.g. Expo OTA updates)?
Any guidance, fixes, or builds verified against Xcode 26 would be appreciated. In particular, we'd like to understand whether there are known issues involving:
IterableEmbeddedManager.reset()IterableEmbeddedUpdateDelegate