Skip to content

iOS: dyld "Symbol not found: std::exception_ptr::__from_native_exception_pointer" on iOS < 18 when built with Xcode 27 #1652

Description

@vnahornyi

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions