From 4f90ebca9b9a6ffffc08185a2d4e9ddc45f6e190 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Wed, 4 Nov 2026 16:46:02 +0100 Subject: [PATCH 1/4] Skip the throw frame source line test on Android 2021.3 --- .github/workflows/test-run-android.yml | 1 + test/IntegrationTest/Integration.Tests.ps1 | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/.github/workflows/test-run-android.yml b/.github/workflows/test-run-android.yml index 6400e761d..8d90dc546 100644 --- a/.github/workflows/test-run-android.yml +++ b/.github/workflows/test-run-android.yml @@ -32,6 +32,7 @@ jobs: HOMEBREW_NO_INSTALL_CLEANUP: 1 SENTRY_DSN: ${{ secrets.SENTRY_TEST_DSN }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_TEST_UNITY_VERSION: ${{ inputs.unity-version }} steps: - name: Checkout diff --git a/test/IntegrationTest/Integration.Tests.ps1 b/test/IntegrationTest/Integration.Tests.ps1 index 6e9f39c20..9f39a191d 100644 --- a/test/IntegrationTest/Integration.Tests.ps1 +++ b/test/IntegrationTest/Integration.Tests.ps1 @@ -447,6 +447,10 @@ Describe "Unity $($env:SENTRY_TEST_PLATFORM) Integration Tests" { Set-ItResult -Skipped -Because "line numbers come from the IL2CPP mappings, which a Mono player does not produce" return } + if ($script:Platform -eq "Android" -and $script:TestSetup.UnityVersion -like "2021.3*") { + Set-ItResult -Skipped -Because "on the Android 2021.3 x86_64 emulator, IL2CPP intermittently reports no stack frames for the thrown exception, so the event carries only the throwing frame without a native address" + return + } $frame = $runEvent.exception.values[0].stacktrace.frames | Where-Object { $_.module -eq "IntegrationTester" -and $_.function -eq "ThrowException" } | From 5c1a689f3d477157b52ef4a81c932a6b62e4a94e Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Wed, 4 Nov 2026 11:29:17 +0100 Subject: [PATCH 2/4] Skip closing the Android and Cocoa SDKs without options --- CHANGELOG.md | 6 ++++++ src/Sentry.Unity.Android/SentryNativeAndroid.cs | 14 ++++++++++++-- src/Sentry.Unity.iOS/SentryNativeCocoa.cs | 14 ++++++++++++-- .../SentryNativeAndroidTests.cs | 10 ++++++++++ .../Sentry.Unity.iOS.Tests/SentryNativeIosTests.cs | 6 ++++++ 5 files changed, 46 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 252fc315b..6e3505371 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +### Fixes + +- The SDK no longer throws a `NullReferenceException` during startup on Android and iOS when it can't load its options, for example when the configuration lives in an OBB file that isn't available yet. ([#PR](https://github.com/getsentry/sentry-unity/pull/PR)) + ## 4.12.0 ### Behavioral Changes diff --git a/src/Sentry.Unity.Android/SentryNativeAndroid.cs b/src/Sentry.Unity.Android/SentryNativeAndroid.cs index 082be4ab3..b77d081ee 100644 --- a/src/Sentry.Unity.Android/SentryNativeAndroid.cs +++ b/src/Sentry.Unity.Android/SentryNativeAndroid.cs @@ -224,11 +224,21 @@ void Refresh() /// /// Closes the native Android support. /// - public static void Close(SentryUnityOptions options) + public static void Close(SentryUnityOptions? options) => + Close(options, ApplicationAdapter.Instance.Platform); + + // For testing + internal static void Close(SentryUnityOptions? options, RuntimePlatform platform) { Logger?.LogInfo("Attempting to close the Android SDK"); - if (!options.IsNativeSupportEnabled()) + if (options is null) + { + Logger?.LogDebug("No options available. Skipping closing the Android SDK"); + return; + } + + if (!options.IsNativeSupportEnabled(platform)) { Logger?.LogDebug("Android Native Support is not enabled. Skipping closing the Android SDK"); return; diff --git a/src/Sentry.Unity.iOS/SentryNativeCocoa.cs b/src/Sentry.Unity.iOS/SentryNativeCocoa.cs index ea913e04d..4e3bb8f9c 100644 --- a/src/Sentry.Unity.iOS/SentryNativeCocoa.cs +++ b/src/Sentry.Unity.iOS/SentryNativeCocoa.cs @@ -132,11 +132,21 @@ internal static void Configure(SentryUnityOptions options, RuntimePlatform platf /// /// Closes the native Cocoa support. /// - public static void Close(SentryUnityOptions options) + public static void Close(SentryUnityOptions? options) => + Close(options, ApplicationAdapter.Instance.Platform); + + // For testing + internal static void Close(SentryUnityOptions? options, RuntimePlatform platform) { Logger?.LogInfo("Attempting to close the Cocoa SDK"); - if (!options.IsNativeSupportEnabled()) + if (options is null) + { + Logger?.LogDebug("No options available. Skipping closing the Cocoa SDK"); + return; + } + + if (!options.IsNativeSupportEnabled(platform)) { Logger?.LogDebug("Cocoa Native Support is not enable. Skipping closing the Cocoa SDK"); return; diff --git a/test/Sentry.Unity.Android.Tests/SentryNativeAndroidTests.cs b/test/Sentry.Unity.Android.Tests/SentryNativeAndroidTests.cs index 73ca5e915..0634514d7 100644 --- a/test/Sentry.Unity.Android.Tests/SentryNativeAndroidTests.cs +++ b/test/Sentry.Unity.Android.Tests/SentryNativeAndroidTests.cs @@ -4,6 +4,7 @@ using NUnit.Framework; using Sentry.Unity.Tests.SharedClasses; using Sentry.Unity.Tests.Stubs; +using UnityEngine; namespace Sentry.Unity.Android.Tests; @@ -36,6 +37,15 @@ public void TearDown() => Interlocked.Exchange(ref SentryNative.ReinstallSentryNativeBackendStrategy!, _originalReinstallSentryNativeBackendStrategy)!; + [Test] + public void Close_OptionsNull_DoesNotCloseSentryJava() + { + _testSentryJava.SentryPresent = true; + + Assert.DoesNotThrow(() => SentryNativeAndroid.Close(null, RuntimePlatform.Android)); + Assert.False(_testSentryJava.CloseCalled); + } + [Test] public void Configure_DefaultConfiguration_SetsScopeObserver() { diff --git a/test/Sentry.Unity.iOS.Tests/SentryNativeIosTests.cs b/test/Sentry.Unity.iOS.Tests/SentryNativeIosTests.cs index eac8b89de..0e15269bd 100644 --- a/test/Sentry.Unity.iOS.Tests/SentryNativeIosTests.cs +++ b/test/Sentry.Unity.iOS.Tests/SentryNativeIosTests.cs @@ -7,6 +7,12 @@ namespace Sentry.Unity.iOS.Tests; public class SentryNativeCocoaTests { + [Test] + public void Close_OptionsNull_DoesNotThrow() + { + Assert.DoesNotThrow(() => SentryNativeCocoa.Close(null, RuntimePlatform.IPhonePlayer)); + } + [Test] public void Configure_DefaultConfiguration_iOS() { From 53537f9475570b90b4f876862e8f691143485be7 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Wed, 4 Nov 2026 11:32:14 +0100 Subject: [PATCH 3/4] Mark the macOS Close options as nullable --- src/Sentry.Unity.MacOS/SentryNativeMacos.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Sentry.Unity.MacOS/SentryNativeMacos.cs b/src/Sentry.Unity.MacOS/SentryNativeMacos.cs index 8e8d3071a..ac11148b7 100644 --- a/src/Sentry.Unity.MacOS/SentryNativeMacos.cs +++ b/src/Sentry.Unity.MacOS/SentryNativeMacos.cs @@ -26,7 +26,7 @@ public static void Configure(SentryUnityOptions options) SentryNativeCocoa.Configure(options); } - public static void Close(SentryUnityOptions options) + public static void Close(SentryUnityOptions? options) { if (options is null) { From 330303d02e64e477e0eadbf28b78093e2b1ad3b4 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Wed, 4 Nov 2026 11:39:36 +0100 Subject: [PATCH 4/4] Add PR link to CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e3505371..738ea3049 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ ### Fixes -- The SDK no longer throws a `NullReferenceException` during startup on Android and iOS when it can't load its options, for example when the configuration lives in an OBB file that isn't available yet. ([#PR](https://github.com/getsentry/sentry-unity/pull/PR)) +- The SDK no longer throws a `NullReferenceException` during startup on Android and iOS when it can't load its options, for example when the configuration lives in an OBB file that isn't available yet. ([#2931](https://github.com/getsentry/sentry-unity/pull/2931)) ## 4.12.0