Skip to content

fix(ios): Re-land SentrySDK.internal migration, bump Cocoa SDK to 9.24.0 - #6541

Draft
alwx wants to merge 2 commits into
mainfrom
alwx/fix/6507
Draft

fix(ios): Re-land SentrySDK.internal migration, bump Cocoa SDK to 9.24.0#6541
alwx wants to merge 2 commits into
mainfrom
alwx/fix/6507

Conversation

@alwx

@alwx alwx commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

📢 Type of change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring

📜 Description

Re-lands #6380 (the PrivateSentrySDKOnlySentrySDK.internal migration), which shipped in 8.19.0 and was reverted in 8.20.0 by #6491, now that the underlying sentry-cocoa bug is fixed.

Three parts:

  1. Bump sentry-cocoa 9.19.1 → 9.24.0 (podspec + xcframework SHA256, via scripts/update-cocoa.sh set-version 9.24.0).
  2. Revert the revert of refactor(ios): Migrate from PrivateSentrySDKOnly to SentrySDK.internal #6380 — applied cleanly, no conflicts. The only commits touching packages/core/ios since the revert were the two release commits.
  3. New regression guardRNSentryCocoaTester/RNSentryCocoaTesterTests/RNSentryScreenshotSourceTests.swift.

Re-landing also restores the two improvements #6491 removed along with the migration: the fetchViewHierarchy nil-guard (returns null instead of a zero-byte attachment when capture fails) and the RNSentryTimeToDisplay extern linkage change.

Important

This re-introduces the RN < 0.75 requirement from 8.19.0: on React Native versions where React-hermes (or another RN pod) is not modularized by default (e.g. RN 0.71), users must add use_modular_headers! to their ios/Podfile. CocoaPods refuses to integrate a Swift pod against non-modular ObjC dependencies, and RNSentryInternal.swift makes RNSentry a Swift pod. Called out in the CHANGELOG.

💡 Motivation and Context

Fixes #6507.

#6380 broke all iOS screenshot capture — Feedback Widget screenshot, attachScreenshot, and Sentry.captureScreenshot() (#6497).

Root cause was in sentry-cocoa, not in RN: constructing SentryInternalApi eagerly reads SentryDependencyContainer.screenshotSource, which was a lazy var whose builder returns nil while startOptions is unset. Being lazy, that nil was cached for the process lifetime. RN reads SentrySDK.internal before SentrySDK.start — from RNSentryStart itself, and from JS integrations calling native methods like fetchNativeAppStart / fetchNativeSdkInfo during init — so the source was reliably poisoned. A targeted RN-side fix wasn't possible because JS controls the timing of those calls, hence the full revert.

getsentry/sentry-cocoa#8578 makes screenshotSource a computed property so getOptionalLazyVar re-runs the builder until startOptions is available, and only then caches. It shipped in 9.24.0.

I also confirmed:

  • SentrySDK.internal is a computed property that builds a fresh SentryInternalApi per access, so the eager read in SentryInternalScreenshotApi.init is harmless once screenshotSource rebuilds.
  • viewHierarchyProvider is still a lazy var, but its builder never touches startOptions, so it cannot be poisoned the same way.
  • No API drift in Sources/Swift/HybridSDK/ between 9.19.1 and 9.24.0 — the only diffs are @_implementationOnly importinternal import. Every symbol RNSentryInternal.swift bridges still exists with the same signature.
  • Nothing in the 9.20.0–9.24.0 cocoa changelog affects RN. enableReplayNetworkDetailsCapturing was removed in 9.22.0 but RN never set it.

💚 How did you test it?

New regression test (RNSentryScreenshotSourceTests): reads SentrySDK.internal before SentrySDK.start, then starts via RNSentryStart.start with attachScreenshot and asserts SentrySDK.internal.screenshot.capture() is non-nil. Verified it is not vacuous:

sentry-cocoa Result
9.19.1 (buggy) XCTAssertNotNil failed — reproduces #6497
9.24.0 (fixed) ✅ passes

Full native suiteRNSentryCocoaTester, Release config, iPhone simulator, Xcode 26.1: 163 tests, 0 failures.

Linters: swiftlint --strict clean (13 files, 0 violations), clang-format clean.

No JS/TS source changed, so no api-report or JS test impact.

📝 Checklist

  • I added tests to verify changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • All tests passing.
  • Public API changes reviewed by another Mobile SDK team member or implemented according to the develop docs spec.
  • No breaking changes.

🔮 Next steps

Needs the ready-to-merge label before merging so the native / E2E / sample-app workflows run — the iOS feedback E2E flow is what surfaced #6497 in the first place and should be confirmed green.

Two pre-existing problems found while writing the regression test, both unrelated to this change and left for follow-up issues:

  1. RNSentryStartTests.swift and RNSentryStartFromFileTests.swift are not in the Xcode test target. They were dropped from project.pbxproj around the v7 merge (6ab6b160) and have not compiled or run since. They no longer build (Options.enableTracing was removed in cocoa v9), and once that's fixed every test in them crashes — see below. I intentionally did not re-enable them here; that's why the new regression test lives in its own file.
  2. RNSentrySDK.start proceeds with options == nil when sentry.options.json is absent or unparseable (packages/core/ios/RNSentrySDK.m L64-72). The @{} fallback also fails validation ("Invalid DSN URL") and returns nil, but the code carries on into updateWithReactDefaults: / configureOptions(...) / startWithOptions:. Identical before and after refactor(ios): Migrate from PrivateSentrySDKOnly to SentrySDK.internal #6380 — both PrivateSentrySDKOnly.optionsWithDictionary:didFailWithError: and SentrySDK.internal.options(fromDictionary:) funnel into the same SentryOptionsInternal initWithDict:, which returns nil on failure. From ObjC it silently no-ops; from Swift (options.dsn = … on an implicitly-unwrapped SentryOptions!) it segfaults.

alwx added 2 commits July 30, 2026 13:27
Reapplies #6380 (reverted in 8.20.0 by #6491) now that the underlying
sentry-cocoa bug is fixed.

#6380 migrated iOS code from the deprecated PrivateSentrySDKOnly SPI to the
SentrySDK.internal Swift API. It shipped in 8.19.0 and broke every iOS
screenshot (Feedback Widget screenshot, attachScreenshot,
Sentry.captureScreenshot) — #6497.

Root cause was in sentry-cocoa: constructing SentryInternalApi eagerly reads
SentryDependencyContainer.screenshotSource, a lazy var whose builder returns
nil while startOptions is unset. Being lazy, that nil was cached for the
process lifetime, and RN reads SentrySDK.internal before SentrySDK.start
(from RNSentryStart, and from JS integrations calling fetchNativeAppStart /
fetchNativeSdkInfo during init). getsentry/sentry-cocoa#8578 makes
screenshotSource a computed property so the builder re-runs until
startOptions is available; it shipped in 9.24.0, which this bumps to.

Adds RNSentryScreenshotSourceTests as a regression guard: it reads
SentrySDK.internal before starting the SDK and asserts screenshot capture
still works. Verified to fail against 9.19.1 and pass against 9.24.0.

Re-landing also restores the two improvements the revert removed: the
fetchViewHierarchy nil-guard (returns null instead of a zero-byte
attachment on capture failure) and the RNSentryTimeToDisplay extern linkage.

Fixes #6507.
@github-actions

Copy link
Copy Markdown
Contributor

Semver Impact of This PR

None (no version bump detected)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


  • fix(ios): Re-land SentrySDK.internal migration, bump Cocoa SDK to 9.24.0 by alwx in #6541

🤖 This preview updates automatically when you update the PR.

@github-actions

Copy link
Copy Markdown
Contributor
Fails
🚫 Pull request is not ready for merge, please add the "ready-to-merge" label to the pull request

Generated by 🚫 dangerJS against 91a3498

#import "RNSentryHexFormatter.h"
#import "RNSentryId.h"
#import <Sentry/PrivateSentrySDKOnly.h>
@import Sentry;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RNSentry+fetchNativeStack.m still calls SentrySDKInternal after removing its private header import

This file drops #import <Sentry/PrivateSentrySDKOnly.h> but still uses [SentrySDKInternal.options debug] at line 14, while every other production file migrated to RNSentryInternal. If SentrySDKInternal is no longer exported by Cocoa SDK 9.24.0, options resolves to nil and local symbolication is silently disabled.

Evidence
  • The hunk removes #import <Sentry/PrivateSentrySDKOnly.h> (line 5), the header that previously declared SentrySDKInternal.
  • [SentrySDKInternal.options debug] on line 14 was never updated to the new RNSentryInternal bridge.
  • SentrySDKInternal is only forward-declared in RNSentry.h with no @implementation in this repo; the Cocoa SDK binary must supply it.
  • Every other production .m/.mm file (e.g. RNSentryStart.m, SentrySDKWrapper.m) was migrated to [RNSentryInternal options] and imports the generated Swift header.
  • Only the test suite still imports PrivateSentrySDKOnly.h to access SentrySDKInternal, confirming it is a private API that the migration intends to leave behind.

Identified by Warden · code-review · QZL-8NM

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reapply iOS SentrySDK.internal migration (#6380) after sentry-cocoa fixes screenshotSource lazy-var poisoning

1 participant