Skip to content

iOS build fails to link (Undefined symbols: SentryInternalSwizzleApi.Mode.oncePerClass) when consuming the default prebuilt Sentry.xcframework #6465

Description

@mikewesthad

What React Native libraries do you use?

Expo Application Services (EAS), Expo (mobile only), Hermes

Are you using sentry.io or on-premise?

sentry.io (SaS)

Are you using any other error monitoring solution alongside Sentry?

Yes

Other Error Monitoring Solution Name

No response

@sentry/react-native SDK Version

8.19.0

How does your development environment look like?

@sentry/react-native: 8.19.0
sentry-cocoa (pinned by RNSentry RNSentry.podspec): 9.19.1
react-native: 0.83.6
expo: 55.0.27
Build: EAS Build, iOS sdk-55 image, device (arm64) release build
SENTRY_USE_XCFRAMEWORK: unset (i.e. the new default prebuilt-xcframework path)

Sentry.init()

Sentry.init({
  dsn: "https://XXX@oXXXX.ingest.us.sentry.io/XXXX",
  release: getSentryReleaseIdentifier(),
  profilesSampleRate: 1.0,
  environment: getEnvironment(),
  attachScreenshot: false,
  attachViewHierarchy: false,
  attachThreads: true,
  attachAllThreads: true,
  dist: Updates.updateId ?? undefined,
});

Steps to Reproduce

  1. Use @sentry/react-native 8.19.0 on iOS with the default integration (prebuilt Sentry.xcframework; SENTRY_USE_XCFRAMEWORK unset).
  2. Build the iOS app for a real device (arm64). Ours is an Expo (CNG) app built on EAS Build (JS-1173 image).
  3. The Xcode/ld link step fails (see Actual Result). Setting SENTRY_USE_XCFRAMEWORK=0 (source build) makes it succeed.

Expected Result

The app links against the prebuilt Sentry.xcframework and builds successfully, with no need to fall back to the source-built CocoaPod.

Actual Result

Link step fails:

Undefined symbols for architecture arm64
┌─ Symbol: enum case for Sentry.SentryInternalSwizzleApi.Mode.oncePerClass(Sentry.SentryInternalSwizzleApi.Mode.Type) -> Sentry.SentryInternalSwizzleApi.Mode
└─ Referenced from: function signature specialization <Arg[1] = Dead> of static RNSentry.RNSentryInternal.swizzleRNSScreenViewDidAppear(hook: () -> ()) -> () in RNSentry[28](RNSentryInternal.o)

ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Likely cause is the interaction of two changes that landed for 8.18/8.19:

SentryInternalSwizzleApi.Mode.oncePerClass is an internal/@_spi Swift symbol that the prebuilt static Sentry.xcframework slice doesn’t vend, so RNSentry (compiled separately) can’t resolve it at link time. Building sentry-cocoa from source (SENTRY_USE_XCFRAMEWORK=0) keeps both in the same module graph and links cleanly.

Activity

  1. moved this to Waiting for: Product Owner in GitHub Issues with 👀 3on Jul 16, 2026
  2. linear-code commented on Jul 16, 2026

    @linear-code
  3. alwx commented on Jul 17, 2026

    @alwx
    Contributor

    Thanks for submitting this, @mikewesthad!
    I've already drafted a PR to solve this issue and will continue with it next week: #6468
    The valid workaround for now would be to use SENTRY_USE_XCFRAMEWORK=0.

  4. moved this from Waiting for: Product Owner to No status in GitHub Issues with 👀 3on Jul 17, 2026
  5. self-assigned this
    on Jul 17, 2026
  6. mikewesthad commented on Jul 17, 2026

    @mikewesthad
    Author

    Thanks! Yeah that's what we ended up using

  7. moved this to Waiting for: Product Owner in GitHub Issues with 👀 3on Jul 17, 2026
  8. added a commit that references this issue on Jul 20, 2026
    e4a99a6
  9. philprime commented on Jul 20, 2026

    @philprime
    Member

    I did an analysis on the prebuilt xcframework to verify if the symbols are really absent, and based on the released artifact, neither the swizzling header nor implementation is simply missing or incorrect.

    I downloaded the exact static XCFramework pinned by React Native:

    Sentry.xcframework.zip 9.19.1
    SHA-256: d6d545af17e49851cda2747b0f45cde78ce08ea37709dde5a956c6b4671224e8
    

    That checksum matches sentry-react-native/packages/core/scripts/sentry_utils.rb.
    The device framework contains:

    • PrivateHeaders/SentrySwizzle.h
    • SentrySwizzle.o
    • SentrySwizzleWrapperHelper.o
    • SentryInternalSwizzleApi.o
    • arm64-apple-ios.private.swiftinterface

    The static binary defines all relevant symbols:

    SentryInternalSwizzleApi.instanceMethod(...)
    SentryInternalSwizzleApi.Mode.oncePerClass
    _OBJC_CLASS_$_SentrySwizzle
    _OBJC_CLASS_$_SentrySwizzleWrapperHelper
    

    The exact mangled symbol required by a separate Swift consumer is:

    _$s6Sentry0A18InternalSwizzleApiV4ModeO12oncePerClassyA2EmFWC
    

    The exact same symbol is defined in the 9.19.1 arm64 framework.

    I also compiled a separate Swift consumer against the XCFramework’s private interface and linked it successfully.

    This means that the statement that the symbol “is not exported from the XCFramework” might not be accurate for the official 9.19.1 artifact.

    The issue is more likely in how the React Native application build integrates the static XCFramework. Possibilities include:

    1. The Sentry static framework is not present in the failing final link command.
    2. The wrong framework slice or an older cached artifact is selected.
    3. A CocoaPods-generated link setting strips or omits the framework in that configuration.
    4. The EAS Xcode/toolchain version changes static Swift linking behavior.
    5. The report shows only the first undefined symbol, while the underlying issue is that the final app target is not linking the relevant Sentry object code.

    The Objective-C workaround succeeds because Objective-C class references interact differently with static archive extraction and -ObjC. That does not prove the Swift definitions are absent.

    Happy to further investigate this but for that I need the full React Native app link invocation, particularly:

    Ld ... arm64
    

    and its complete arguments. Then verify:

    • -framework Sentry is present.
    • Which Sentry.framework/Sentry path is selected.
    • Which architecture slice is used.
    • Whether -ObjC, -all_load, or -force_load is present.
    • Whether the selected framework defines the exact mangled symbol.
  10. moved this from Waiting for: Product Owner to No status in GitHub Issues with 👀 3on Jul 20, 2026
  11. mikewesthad commented on Jul 20, 2026

    @mikewesthad
    Author

    Ahhh shoot. Sorry! It turns out an internal native dependency had s.dependency 'Sentry', '~> 9.0' in the podspec, so it looks like we were running into a two-Sentry-provider ABI mismatch. SENTRY_USE_XCFRAMEWORK=0 was letting us compile against the same source module and bypass the mismatch

  12. philprime commented on Jul 21, 2026

    @philprime
    Member

    No worries! Happy to read that you were able to find the root cause.

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

Metadata

Metadata

Assignees

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions