Skip to content

Conversation

@antonis
Copy link
Contributor

@antonis antonis commented Jan 26, 2026

📢 Type of change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring

📜 Description

Follow up to #4472 (v6) > #5470 (v7) targeting v8 #5501

  • Capture App Start errors and crashes by initializing Sentry from sentry.options.json (#4472)

    Create sentry.options.json in the React Native project root and set options the same as you currently have in Sentry.init in JS.

    {
        "dsn": "https://key@example.io/value",
    }

    Initialize Sentry on the native layers by newly provided native methods.

    import io.sentry.react.RNSentrySDK
    
    class MainApplication : Application(), ReactApplication {
        override fun onCreate() {
            super.onCreate()
            RNSentrySDK.init(this)
        }
    }
    #import <RNSentry/RNSentry.h>
    
    @implementation AppDelegate
    - (BOOL)application:(UIApplication *)application
        didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        [RNSentrySDK start];
        return [super application:application didFinishLaunchingWithOptions:launchOptions];
    }
    @end
  • Add RNSentrySDK APIs support to @sentry/react-native/expo plugin (#4633)

    • Adds useNativeInit option to automatically initialize Sentry natively before JavaScript loads, enabling capture of app start errors
    {
      "expo": {
        "plugins": [
          [
            "@sentry/react-native/expo",
            {
              "useNativeInit": true
            }
          ]
        ]
      }
    }

Changes

  • Load optionsFile into the JS bundle during Metro bundle process (#4476)
  • Add experimental version of startWithConfigureOptions for Apple platforms (#4444)
  • Add experimental version of init with optional OptionsConfiguration<SentryAndroidOptions> for Android (#4451)
  • Add initialization using sentry.options.json for Apple platforms (#4447)
  • Add initialization using sentry.options.json for Android (#4451)
  • Merge options from file with Sentry.init options in JS (#4510)

Internal

  • Extract iOS native initialization to standalone structures (#4442)
  • Extract Android native initialization to standalone structures (#4445)

Note

The feature the feature should be 100% backwards compatible and opt-in. Users who don't create sentry.options.json or call RNSentrySDK.start()/init() will experience zero changes to their existing Sentry implementation. The traditional JS-only initialization path remains fully functional and is the default behavior.

📝 Documentation PR: getsentry/sentry-docs#16170

💡 Motivation and Context

Fixes #3608

Previously, React Native apps couldn't capture errors that occurred during app startup before JavaScript initialized, because Sentry was only initialized from JavaScript code (Sentry.init()). This meant crashes during:

  • Native module initialization
  • JavaScript bundle loading
  • Early React Native bridge setup

were never captured.

💚 How did you test it?

CI, Manually

📝 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
  • No breaking changes

🔮 Next steps

#skip-changelog

krystofwoldrich and others added 30 commits January 21, 2025 17:22
…ructures (#4445)

* Extract Android SDK Init

* Update tests

* Adds changelog

* Fix lint issues

* Rename RNSentryStart instance for clarity

* Converts RNSentryStart to utility class

* Update CHANGELOG.md

---------

Co-authored-by: Krystof Woldrich <31292499+krystofwoldrich@users.noreply.github.com>
* Convert json object to writable map

* Make class/methods package-private(default)
- Resolved merge conflicts across iOS, Android, and JavaScript/TypeScript code
- Updated iOS implementation to use RNSentryStart API
- Fixed Android compilation errors for Sentry Android SDK v7 compatibility
- Removed deprecated API calls (setEnableTracing, getPackages, getIntegrations)
- Updated Gradle build scripts and resolved conflict markers
- All builds verified: iOS, Android, and Expo sample apps compile successfully
@github-actions
Copy link
Contributor

github-actions bot commented Jan 26, 2026

iOS (new) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 1209.73 ms 1209.33 ms -0.40 ms
Size 3.38 MiB 4.68 MiB 1.30 MiB

Baseline results on branch: v8

Startup times

Revision Plain With Sentry Diff
206e87e+dirty 1197.12 ms 1204.25 ms 7.13 ms
b4fa5b4+dirty 1213.59 ms 1211.26 ms -2.33 ms
d6aa223+dirty 1216.76 ms 1213.40 ms -3.37 ms
12fba4a+dirty 1209.43 ms 1217.08 ms 7.65 ms
bc8a1ed+dirty 1198.66 ms 1200.60 ms 1.94 ms
fa0d109+dirty 1206.81 ms 1205.38 ms -1.43 ms

App size

Revision Plain With Sentry Diff
206e87e+dirty 3.38 MiB 4.67 MiB 1.29 MiB
b4fa5b4+dirty 3.44 MiB 4.66 MiB 1.22 MiB
d6aa223+dirty 3.38 MiB 4.67 MiB 1.29 MiB
12fba4a+dirty 3.38 MiB 4.67 MiB 1.29 MiB
bc8a1ed+dirty 3.44 MiB 4.66 MiB 1.22 MiB
fa0d109+dirty 3.38 MiB 4.67 MiB 1.29 MiB

Previous results on branch: antonis/capture-app-start-errors-v8

Startup times

Revision Plain With Sentry Diff
88812b1+dirty 1210.98 ms 1215.22 ms 4.24 ms
82de722+dirty 1210.87 ms 1217.00 ms 6.13 ms
b4df5a0+dirty 1217.06 ms 1221.61 ms 4.55 ms

App size

Revision Plain With Sentry Diff
88812b1+dirty 3.38 MiB 4.67 MiB 1.29 MiB
82de722+dirty 3.38 MiB 4.67 MiB 1.29 MiB
b4df5a0+dirty 3.38 MiB 4.67 MiB 1.29 MiB

@github-actions
Copy link
Contributor

github-actions bot commented Jan 26, 2026

iOS (legacy) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 1196.92 ms 1203.92 ms 7.00 ms
Size 3.38 MiB 4.68 MiB 1.30 MiB

Baseline results on branch: v8

Startup times

Revision Plain With Sentry Diff
206e87e+dirty 1184.11 ms 1183.19 ms -0.92 ms
b4fa5b4+dirty 1203.83 ms 1207.13 ms 3.30 ms
d6aa223+dirty 1192.33 ms 1208.17 ms 15.84 ms
12fba4a+dirty 1214.20 ms 1223.30 ms 9.09 ms
bc8a1ed+dirty 1194.70 ms 1201.18 ms 6.48 ms
fa0d109+dirty 1216.02 ms 1220.67 ms 4.65 ms

App size

Revision Plain With Sentry Diff
206e87e+dirty 3.38 MiB 4.67 MiB 1.29 MiB
b4fa5b4+dirty 3.44 MiB 4.66 MiB 1.22 MiB
d6aa223+dirty 3.38 MiB 4.67 MiB 1.29 MiB
12fba4a+dirty 3.38 MiB 4.67 MiB 1.29 MiB
bc8a1ed+dirty 3.44 MiB 4.66 MiB 1.22 MiB
fa0d109+dirty 3.38 MiB 4.67 MiB 1.29 MiB

Previous results on branch: antonis/capture-app-start-errors-v8

Startup times

Revision Plain With Sentry Diff
88812b1+dirty 1216.63 ms 1215.55 ms -1.08 ms
82de722+dirty 1213.09 ms 1208.90 ms -4.19 ms
b4df5a0+dirty 1213.04 ms 1218.59 ms 5.55 ms

App size

Revision Plain With Sentry Diff
88812b1+dirty 3.38 MiB 4.67 MiB 1.29 MiB
82de722+dirty 3.38 MiB 4.67 MiB 1.29 MiB
b4df5a0+dirty 3.38 MiB 4.67 MiB 1.29 MiB

@antonis
Copy link
Contributor Author

antonis commented Jan 27, 2026

@sentry review

@lucas-zimerman
Copy link
Collaborator

No noticeable impact on iOS, the app size increase by adding sentry on java is interesting though, but no extra impact from this PR.

@antonis
Copy link
Contributor Author

antonis commented Jan 27, 2026

No noticeable impact on iOS, the app size increase by adding sentry on java is interesting though, but no extra impact from this PR.

That's a good catch @lucas-zimerman 🤔

I wonder if this has to do with the Gradle Plugin bump #5578 on the v8 base branch #5501

[
"@sentry/react-native/expo",
{
"useNativeInit": true
Copy link
Collaborator

Choose a reason for hiding this comment

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

Q: Do all sentry options work here? we should document this feature.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the only added option in the plugin. I've started a documentation PR in getsentry/sentry-docs#16170

@antonis
Copy link
Contributor Author

antonis commented Jan 27, 2026

No noticeable impact on iOS, the app size increase by adding sentry on java is interesting though, but no extra impact from this PR.

That's a good catch @lucas-zimerman 🤔

I wonder if this has to do with the Gradle Plugin bump #5578 on the v8 base branch #5501

Looking at it again I think the With Sentry sizes are the same with the base branch 48.40 MiB (legacy), 49.22 MiB (new)

Copy link
Collaborator

@lucas-zimerman lucas-zimerman left a comment

Choose a reason for hiding this comment

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

After a complete PR review and also loads of tokens, I can really say, LGTM!

antonis and others added 2 commits January 27, 2026 14:05
Co-authored-by: LucasZF <lucas-zimerman1@hotmail.com>
@antonis
Copy link
Contributor Author

antonis commented Jan 27, 2026

@sentry review

* fix(android): Fix ConcurrentModificationException when disabling native crash handling

When enableNativeCrashHandling is set to false, the code was iterating over
the integrations list with a for-each loop while calling remove() directly,
which causes a ConcurrentModificationException at runtime.

Fixed by using Java 8's removeIf() method which safely handles iteration
and removal in a single operation. This is more concise and follows modern
Java best practices.

Added unit tests to verify the fix and ensure integrations are properly
removed without throwing exceptions.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Lint fix

---------

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
antonis and others added 2 commits January 28, 2026 17:59
…carUrl

The code attempted to read defaultSidecarUrl without checking if the key
exists in the options map. This caused a NoSuchKeyException crash during
startup when spotlight was set to true in sentry.options.json without
providing defaultSidecarUrl.

Added key existence check to match iOS implementation behavior and prevent
the crash while maintaining backward compatibility.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* test(e2e): Add auto init from JS tests for Android

Implements Android E2E testing infrastructure to verify both manual native initialization and auto initialization from JavaScript, matching the iOS implementation and resolving issue #4912.

Key additions:
- Jest configs for android.auto and android.manual test modes
- Build scripts that toggle SENTRY_DISABLE_NATIVE_START at compile time
- Test scripts to run auto and manual test suites separately
- App start crash testing via flag file mechanism
- TestControlModule to enable/disable crash-on-start from JS
- Comprehensive E2E test documentation

Unlike iOS which uses launch arguments at runtime, Android requires separate builds with different build configurations to control native initialization.

Closes #4912

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix(e2e): Add scrolling to find crash control buttons in Android test

The crash control buttons are off-screen, so the Maestro flow needs to
scroll to find them before tapping. This matches the pattern used in
other Android E2E tests.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix(e2e): Make Android crash flag auto-expire after one crash

The crash flag file was persisting across app launches, causing the app
to crash indefinitely. Now the flag auto-deletes when read, allowing:
1. First launch: Enable flag
2. Second launch: Read flag, delete it, then crash
3. Third launch: Start normally and send crash report

This solves the chicken-and-egg problem where the app couldn't reach
JavaScript to clear the flag because it kept crashing before JS loaded.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix(e2e): Handle wrapped exceptions in Android crash test

Android wraps exceptions thrown in Application.onCreate() with:
"Unable to create application... RuntimeException: <original message>"

Updated the test to check if ANY exception in the chain contains our
intentional crash message, rather than expecting an exact match on the
first exception.

Test now passes locally and should pass in CI.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Clean up notes for now

---------

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
antonis and others added 2 commits January 29, 2026 14:39
# Conflicts:
#	samples/react-native/android/app/build.gradle
…ions

Fixes a crash on Android startup when initializing from sentry.options.json
without dsn or devServerUrl fields. The code was calling getString() on
ReadableMap without checking if the keys exist first, which throws
NoSuchKeyException for missing keys.

Both fields are optional in configuration files, so the code now checks
for key existence before accessing values, returning null when keys are
missing. This matches the pattern used throughout the rest of the file
and is already handled correctly by the null-checks in the breadcrumb
filter logic.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@antonis antonis merged commit d5c32e3 into v8 Jan 29, 2026
100 of 108 checks passed
@antonis antonis deleted the antonis/capture-app-start-errors-v8 branch January 29, 2026 15:26
antonis added a commit to getsentry/sentry-docs that referenced this pull request Jan 29, 2026
<!-- Use this checklist to make sure your PR is ready for merge. You may
delete any sections you don't need. -->

## DESCRIBE YOUR PR
*Tell us what you're changing and why. If your PR **resolves an issue**,
please link it so it closes automatically.*

## IS YOUR CHANGE URGENT?  

Help us prioritize incoming PRs by letting us know when the change needs
to go live.
- [ ] Urgent deadline (GA date, etc.): <!-- ENTER DATE HERE -->
- [ ] Other deadline: <!-- ENTER DATE HERE -->
- [x] None: Not urgent, can wait up to 1 week+

After getsentry/sentry-react-native#5582 is
released

## SLA

- Teamwork makes the dream work, so please add a reviewer to your PRs.
- Please give the docs team up to 1 week to review your PR unless you've
added an urgent due date to it.
Thanks in advance for your help!

## PRE-MERGE CHECKLIST

*Make sure you've checked the following before merging your changes:*

- [ ] Checked Vercel preview for correctness, including links
- [ ] PR was reviewed and approved by any necessary SMEs (subject matter
experts)
- [ ] PR was reviewed and approved by a member of the [Sentry docs
team](https://github.com/orgs/getsentry/teams/docs)

## LEGAL BOILERPLATE

<!-- Sentry employees and contractors can delete or ignore this section.
-->

Look, I get it. The entity doing business as "Sentry" was incorporated
in the State of Delaware in 2015 as Functional Software, Inc. and is
gonna need some rights from me in order to utilize my contributions in
this here PR. So here's the deal: I retain all rights, title and
interest in and to my contributions, and by keeping this boilerplate
intact I confirm that Sentry can use, modify, copy, and redistribute my
contributions, under Sentry's choice of terms.

## EXTRA RESOURCES

- [Sentry Docs contributor guide](https://docs.sentry.io/contributing/)
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.

5 participants