What happened?
After switching our React Native app (RN 0.87.1, New Architecture, iOS deployment target 15.1) to Xcode 27 / iOS 27 SDK, the app aborts at launch in dyld on every iOS version below 18.0 (verified on the iOS 17.5 simulator). iOS 27 launches fine.
__ZNSt13exception_ptr31__from_native_exception_pointerEPv (std::exception_ptr::__from_native_exception_pointer(void*)) is only present in the iOS 18.0+ system libc++. In the Xcode 27 libc++ headers, std::make_exception_ptr uses it when _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION is set. That macro maps to _LIBCPP_INTRODUCED_IN_LLVM_18 (iOS 18.0) in __configuration/availability.h.
I checked every object file in the Debug build. Only NitroModules.build/.../RuntimeError.o references the symbol, i.e. the object produced from ios/core/RuntimeError.swift. That file calls margelo.nitro.makeException(...) through Swift C++ interop, and ios/utils/RuntimeError.hpp implements it as:
static inline std::exception_ptr makeException(const std::string& message) {
return std::make_exception_ptr(std::runtime_error(message));
}
The C++ translation units of NitroModules compiled with the same headers do not reference the symbol, and RuntimeError.o has minos 15.1 in LC_BUILD_VERSION. So the libc++ availability gating seems to be bypassed only when this inline function is emitted from the Swift C++ interop compilation (explicit module build in Xcode 27). I could not reproduce it with a standalone swiftc -cxx-interoperability-mode=default -target arm64-apple-ios15.1-simulator file, so the exact trigger inside the Xcode build is still unclear.
makeException is the same in 0.35.2, 0.36.5 and 0.37.1.
Workaround we applied (via a postinstall patch): use the libc++ fallback path, which only needs std::current_exception / __cxa_* and links on every iOS version:
static inline std::exception_ptr makeException(const std::string& message) {
try {
throw std::runtime_error(message);
} catch (...) {
return std::current_exception();
}
}
With this change the app launches on iOS 17.5 and on iOS 27. Happy to open a PR with it if that's the preferred fix.
Reproduceable Code
// No custom HybridObjects needed — any app that links NitroModules (e.g. react-native-mmkv 4.3.2)
// Build with Xcode 27 (27A266a), IPHONEOS_DEPLOYMENT_TARGET = 15.1, run on an iOS 17.x simulator/device.
Relevant log output
Termination Reason: Namespace DYLD, Code 4, Symbol missing
Symbol not found: __ZNSt13exception_ptr31__from_native_exception_pointerEPv
Referenced from: <1A0A98D5-DFB1-3A48-8515-8B386796B566> .../megasport.app/megasport
Expected in: <27A11D15-9506-3776-8D00-9F34BEA3ECB1> /Volumes/VOLUME/*/libc++.1.dylib
(terminated at launch; ignore backtrace)
$ nm -u NitroModules.build/Objects-normal/arm64/RuntimeError.o | grep from_native
__ZNSt13exception_ptr31__from_native_exception_pointerEPv
Device
iPhone SE (3rd generation) simulator (iOS 17.5) — crashes; iPhone 17 simulator (iOS 27.0) — works. Built with Xcode 27.0 (27A266a) on macOS 27.0.
Nitro Modules Version
0.36.5 (same makeException in 0.37.1)
Nitrogen Version
Not used directly (react-native-mmkv 4.3.2 is generated with nitrogen 0.35.9)
Can you reproduce this issue in the Nitro Example app here?
I didn't try
Additional information
- React Native 0.87.1, New Architecture (bridgeless), not using Expo
- No existing issues found for
__from_native_exception_pointer
What happened?
After switching our React Native app (RN 0.87.1, New Architecture, iOS deployment target 15.1) to Xcode 27 / iOS 27 SDK, the app aborts at launch in dyld on every iOS version below 18.0 (verified on the iOS 17.5 simulator). iOS 27 launches fine.
__ZNSt13exception_ptr31__from_native_exception_pointerEPv(std::exception_ptr::__from_native_exception_pointer(void*)) is only present in the iOS 18.0+ systemlibc++. In the Xcode 27libc++headers,std::make_exception_ptruses it when_LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTIONis set. That macro maps to_LIBCPP_INTRODUCED_IN_LLVM_18(iOS 18.0) in__configuration/availability.h.I checked every object file in the Debug build. Only
NitroModules.build/.../RuntimeError.oreferences the symbol, i.e. the object produced fromios/core/RuntimeError.swift. That file callsmargelo.nitro.makeException(...)through Swift C++ interop, andios/utils/RuntimeError.hppimplements it as:The C++ translation units of NitroModules compiled with the same headers do not reference the symbol, and
RuntimeError.ohasminos 15.1inLC_BUILD_VERSION. So the libc++ availability gating seems to be bypassed only when this inline function is emitted from the Swift C++ interop compilation (explicit module build in Xcode 27). I could not reproduce it with a standaloneswiftc -cxx-interoperability-mode=default -target arm64-apple-ios15.1-simulatorfile, so the exact trigger inside the Xcode build is still unclear.makeExceptionis the same in 0.35.2, 0.36.5 and 0.37.1.Workaround we applied (via a postinstall patch): use the libc++ fallback path, which only needs
std::current_exception/__cxa_*and links on every iOS version:With this change the app launches on iOS 17.5 and on iOS 27. Happy to open a PR with it if that's the preferred fix.
Reproduceable Code
Relevant log output
Device
iPhone SE (3rd generation) simulator (iOS 17.5) — crashes; iPhone 17 simulator (iOS 27.0) — works. Built with Xcode 27.0 (27A266a) on macOS 27.0.
Nitro Modules Version
0.36.5 (same
makeExceptionin 0.37.1)Nitrogen Version
Not used directly (react-native-mmkv 4.3.2 is generated with nitrogen 0.35.9)
Can you reproduce this issue in the Nitro Example app here?
I didn't try
Additional information
__from_native_exception_pointer