Skip to content

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

Open
alwx wants to merge 4 commits into
mainfrom
alwx/fix/6507
Open

fix(ios): Re-land SentrySDK.internal migration, bump Cocoa SDK to 9.24.0#6541
alwx wants to merge 4 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.

@github-actions

github-actions Bot commented Jul 30, 2026

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
  • chore(deps): update Wizard to v7.0.0 by github-actions in #6558
  • chore(deps): bump the codeql-action group with 3 updates by dependabot in #6553
  • chore(deps): bump getsentry/craft/.github/workflows/changelog-preview.yml from 2.26.14 to 2.28.0 by dependabot in #6554
  • chore(deps): bump fast-uri from 3.1.4 to 3.1.5 by dependabot in #6560
  • chore(deps): bump getsentry/craft from 2.26.14 to 2.28.0 by dependabot in #6556
  • chore(deps): bump ip-address from 10.2.0 to 10.4.0 by dependabot in #6557
  • chore(deps): bump undici from 6.27.0 to 6.28.0 by dependabot in #6559
  • chore(deps): bump actions/setup-java from 5.6.0 to 5.7.0 by dependabot in #6555
  • chore(deps): bump brace-expansion from 1.1.16 to 1.1.18 by dependabot in #6552
  • fix(expo): resolve plugin config when registered as bare '@sentry/react-native' by antonis in #6543
  • fix(ios): make the RNSentry SPEC CHECKSUM in Podfile.lock machine-independent by alwx in #6534
  • chore(deps): update Android SDK to v8.51.0 by github-actions in #6539
  • chore(deps): update Sentry Android Gradle Plugin to v6.17.0 by github-actions in #6544
  • feat(core): Extend TurboModule instrumentation to legacy NativeModules by alwx in #6504
  • feat(ios): Introduce enableMetricKit option by alwx in #6540

🤖 This preview updates automatically when you update the PR.

Comment thread packages/core/ios/RNSentry+fetchNativeStack.m
Reapplies #6380 (reverted in 8.20.0 by #6491) now that the underlying
sentry-cocoa bug is fixed.

#6380 migrated the iOS code off the deprecated PrivateSentrySDKOnly SPI onto
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.

RNSentry+fetchNativeStack.m was the last production file still reading
options through the hand-rolled SentrySDKInternal redeclaration in
RNSentry.h. It now goes through SentrySDKWrapper.debug like the rest of
RNSentry.mm, and the redeclaration is gone.

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.
@alwx
alwx marked this pull request as ready for review August 3, 2026 08:39
Comment thread CHANGELOG.md Outdated
Comment thread CHANGELOG.md Outdated

Re-lands [#6380](https://github.com/getsentry/sentry-react-native/pull/6380), which was reverted in 8.20.0 because it broke iOS screenshot capture ([#6497](https://github.com/getsentry/sentry-react-native/issues/6497)). The underlying sentry-cocoa bug is fixed in 9.24.0.

The `RNSentry` pod now contains Swift code. On React Native versions where RN pods are not modularized by default (e.g. RN 0.71), add `use_modular_headers!` to your `ios/Podfile`.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

It would be nice to add a follow-up PR on Sentry Docs troubleshooting area, with the error users on old React Native will face with it and how to fix it.

@lucas-zimerman lucas-zimerman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

left some notes on the changelog file, overall the code looks good! lets do the final nits on the changelog.md and ship it!

@lucas-zimerman lucas-zimerman added the ready-to-merge Triggers the full CI test suite label Aug 4, 2026
@sentry

sentry Bot commented Aug 4, 2026

Copy link
Copy Markdown

📲 Install Builds

Android

🔗 App Name App ID Version Configuration
Sentry RN io.sentry.reactnative.sample 8.21.0 (101) Release

⚙️ sentry-react-native Build Distribution Settings

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Android (legacy) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 417.10 ms 450.64 ms 33.54 ms
Size 49.74 MiB 55.44 MiB 5.70 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
bc0d8cf+dirty 412.37 ms 466.26 ms 53.89 ms
c823bb5+dirty 409.87 ms 478.57 ms 68.70 ms
774257e+dirty 407.09 ms 447.46 ms 40.37 ms
ae37560+dirty 470.40 ms 564.12 ms 93.72 ms
a3265b6+dirty 406.86 ms 449.84 ms 42.98 ms
5125c43+dirty 497.18 ms 543.78 ms 46.60 ms
1e5d96d+dirty 519.43 ms 543.62 ms 24.19 ms
94af3bd+dirty 503.48 ms 542.37 ms 38.89 ms
3ce5254+dirty 410.57 ms 448.48 ms 37.91 ms
68672fc+dirty 425.02 ms 487.56 ms 62.54 ms

App size

Revision Plain With Sentry Diff
bc0d8cf+dirty 48.30 MiB 53.48 MiB 5.18 MiB
c823bb5+dirty 48.30 MiB 53.58 MiB 5.28 MiB
774257e+dirty 48.30 MiB 53.58 MiB 5.28 MiB
ae37560+dirty 48.30 MiB 53.60 MiB 5.29 MiB
a3265b6+dirty 48.30 MiB 53.58 MiB 5.28 MiB
5125c43+dirty 48.30 MiB 53.54 MiB 5.24 MiB
1e5d96d+dirty 49.74 MiB 54.81 MiB 5.07 MiB
94af3bd+dirty 48.30 MiB 53.57 MiB 5.26 MiB
3ce5254+dirty 43.75 MiB 48.12 MiB 4.37 MiB
68672fc+dirty 48.30 MiB 53.61 MiB 5.31 MiB

Previous results on branch: alwx/fix/6507

Startup times

Revision Plain With Sentry Diff
d119841+dirty 463.53 ms 497.50 ms 33.97 ms
415b9ce+dirty 436.80 ms 510.10 ms 73.30 ms

App size

Revision Plain With Sentry Diff
d119841+dirty 49.74 MiB 55.44 MiB 5.70 MiB
415b9ce+dirty 49.74 MiB 55.44 MiB 5.70 MiB

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

iOS (legacy) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 3839.26 ms 1214.80 ms -2624.45 ms
Size 5.08 MiB 6.72 MiB 1.64 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
21a1e70+dirty 3834.15 ms 1218.43 ms -2615.73 ms
882f8ae+dirty 3840.30 ms 1224.41 ms -2615.88 ms
15d4514+dirty 3840.17 ms 1225.79 ms -2614.38 ms
0b5a379+dirty 3828.91 ms 1214.12 ms -2614.79 ms
f3215d3+dirty 3842.73 ms 1219.33 ms -2623.40 ms
ab203f9+dirty 3848.07 ms 1219.71 ms -2628.35 ms
6177334+dirty 3834.85 ms 1217.58 ms -2617.28 ms
5257d80+dirty 3854.39 ms 1234.28 ms -2620.11 ms
9474ead+dirty 3864.29 ms 1223.55 ms -2640.74 ms
1122a96+dirty 3823.10 ms 1218.64 ms -2604.46 ms

App size

Revision Plain With Sentry Diff
21a1e70+dirty 4.98 MiB 6.46 MiB 1.49 MiB
882f8ae+dirty 5.15 MiB 6.70 MiB 1.54 MiB
15d4514+dirty 5.15 MiB 6.70 MiB 1.55 MiB
0b5a379+dirty 5.15 MiB 6.70 MiB 1.54 MiB
f3215d3+dirty 5.15 MiB 6.67 MiB 1.52 MiB
ab203f9+dirty 4.98 MiB 6.51 MiB 1.53 MiB
6177334+dirty 5.15 MiB 6.68 MiB 1.53 MiB
5257d80+dirty 5.15 MiB 6.69 MiB 1.54 MiB
9474ead+dirty 5.15 MiB 6.71 MiB 1.55 MiB
1122a96+dirty 5.15 MiB 6.68 MiB 1.53 MiB

Previous results on branch: alwx/fix/6507

Startup times

Revision Plain With Sentry Diff
d119841+dirty 3830.88 ms 1218.49 ms -2612.39 ms

App size

Revision Plain With Sentry Diff
d119841+dirty 5.08 MiB 6.72 MiB 1.64 MiB

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

iOS (new) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 3851.11 ms 1226.55 ms -2624.56 ms
Size 5.08 MiB 6.72 MiB 1.64 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
64630e5+dirty 3845.49 ms 1215.19 ms -2630.30 ms
b0d3373+dirty 3842.49 ms 1218.49 ms -2624.00 ms
b04af96+dirty 3830.54 ms 1206.11 ms -2624.44 ms
f9c1ed4+dirty 3842.09 ms 1220.70 ms -2621.40 ms
09a902f+dirty 3847.65 ms 1221.31 ms -2626.34 ms
44abcc2+dirty 3841.42 ms 1214.77 ms -2626.65 ms
acd838e+dirty 3835.94 ms 1215.87 ms -2620.07 ms
bfba737+dirty 3834.18 ms 1222.80 ms -2611.38 ms
ce7b368+dirty 3851.41 ms 1222.37 ms -2629.04 ms
4e0ba9c+dirty 3856.39 ms 1234.44 ms -2621.95 ms

App size

Revision Plain With Sentry Diff
64630e5+dirty 4.98 MiB 6.46 MiB 1.49 MiB
b0d3373+dirty 5.15 MiB 6.68 MiB 1.53 MiB
b04af96+dirty 4.98 MiB 6.54 MiB 1.56 MiB
f9c1ed4+dirty 4.98 MiB 6.50 MiB 1.53 MiB
09a902f+dirty 4.98 MiB 6.46 MiB 1.49 MiB
44abcc2+dirty 4.98 MiB 6.55 MiB 1.57 MiB
acd838e+dirty 5.15 MiB 6.70 MiB 1.55 MiB
bfba737+dirty 4.98 MiB 6.51 MiB 1.53 MiB
ce7b368+dirty 4.98 MiB 6.51 MiB 1.53 MiB
4e0ba9c+dirty 5.15 MiB 6.67 MiB 1.51 MiB

Previous results on branch: alwx/fix/6507

Startup times

Revision Plain With Sentry Diff
d119841+dirty 3847.66 ms 1218.17 ms -2629.49 ms
415b9ce+dirty 3839.34 ms 1217.42 ms -2621.92 ms

App size

Revision Plain With Sentry Diff
d119841+dirty 5.08 MiB 6.72 MiB 1.64 MiB
415b9ce+dirty 5.08 MiB 6.72 MiB 1.64 MiB

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Android (new) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 422.02 ms 478.16 ms 56.14 ms
Size 49.74 MiB 55.44 MiB 5.70 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
244f6e8+dirty 445.89 ms 463.32 ms 17.43 ms
c2e182c+dirty 468.50 ms 545.44 ms 76.94 ms
5fe1c6c+dirty 365.84 ms 408.62 ms 42.78 ms
3d377b5+dirty 425.38 ms 440.67 ms 15.30 ms
3a829f0+dirty 410.78 ms 454.22 ms 43.44 ms
9c84b9a+dirty 429.26 ms 448.90 ms 19.64 ms
40c9884+dirty 453.76 ms 478.98 ms 25.22 ms
bc0d8cf+dirty 407.66 ms 461.35 ms 53.69 ms
7d6fd3a+dirty 435.06 ms 458.78 ms 23.72 ms
68672fc+dirty 407.55 ms 442.96 ms 35.41 ms

App size

Revision Plain With Sentry Diff
244f6e8+dirty 49.74 MiB 55.38 MiB 5.63 MiB
c2e182c+dirty 49.74 MiB 54.85 MiB 5.11 MiB
5fe1c6c+dirty 43.94 MiB 49.00 MiB 5.06 MiB
3d377b5+dirty 43.94 MiB 49.00 MiB 5.06 MiB
3a829f0+dirty 48.30 MiB 53.58 MiB 5.28 MiB
9c84b9a+dirty 49.74 MiB 55.36 MiB 5.62 MiB
40c9884+dirty 49.74 MiB 55.09 MiB 5.34 MiB
bc0d8cf+dirty 48.30 MiB 53.48 MiB 5.18 MiB
7d6fd3a+dirty 43.94 MiB 49.00 MiB 5.06 MiB
68672fc+dirty 48.30 MiB 53.61 MiB 5.31 MiB

Previous results on branch: alwx/fix/6507

Startup times

Revision Plain With Sentry Diff
d119841+dirty 431.41 ms 477.02 ms 45.61 ms
415b9ce+dirty 428.77 ms 475.12 ms 46.35 ms

App size

Revision Plain With Sentry Diff
d119841+dirty 49.74 MiB 55.44 MiB 5.70 MiB
415b9ce+dirty 49.74 MiB 55.44 MiB 5.70 MiB

@lucas-zimerman lucas-zimerman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The `sentry-consumption: cocoapods` sample build failed on this branch with
"None of your spec sources contain a spec satisfying the dependency:
Sentry (= 9.24.0)".

sentry-cocoa deleted `Sentry.podspec` and removed the `cocoapods` craft
publishing target in 9.20.0, so 9.19.1 is the last version ever pushed to the
CocoaPods trunk (verified: trunk serves 9.19.1 but 404s on 9.24.0). That makes
`SENTRY_USE_XCFRAMEWORK=0` -> `s.dependency 'Sentry', <version>` unresolvable
for every version this SDK will ship from now on. A podspec cannot point
`s.dependency` at a git source, so the fallback cannot be repaired.

It stayed green on main only because main still pins 9.19.1.

Replace the fallback with a raise explaining why it is gone and pointing at
SENTRY_XCFRAMEWORK_CACHE_DIR for builds without GitHub Releases access, and
drop the CI matrix entry that exercised it.

Also apply review feedback on the changelog: move the entry to the top of
Unreleased and turn the modular-headers note into a [!WARNING] callout so
RN < 0.75 users see the required Podfile change immediately.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 3e6eef7. Configure here.

Comment thread CHANGELOG.md
@alwx
alwx requested a review from lucas-zimerman August 4, 2026 11:51

@lucas-zimerman lucas-zimerman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM!

@alwx
alwx enabled auto-merge (squash) August 5, 2026 10:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-merge Triggers the full CI test suite

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

2 participants