[Android] Native SIGSEGV (SEGV_MAPERR, fault addr 0x0) in libmonosgen-2.0.so when navigating from the initial Shell route to any second page — Release only, reproduces on physical device AND emulator, both .NET 10 and .NET 8
- Dominant language
- C#
- Stars
- 23.3k
- Forks
- 2k
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 290
Description
## Description
In Release configuration on Android, navigating from a MAUI Shell app's initial route to *any* second page crashes the process with a native null-pointer dereference in the Mono runtime. The same build navigates fine in Debug. The crash is:
- **independent of the destination page's content** — a page containing a single `Label` crashes identically to a page with a full dependency chain (DI-resolved services, MSAL, view models);
- **independent of the first page's complexity** — a first page with a full real dependency chain (including constructing a real `Microsoft.Identity.Client.IPublicClientApplication` via `PublicClientApplicationBuilder.Build()`) renders perfectly every time;
- **independent of the navigation mechanism** — reproduces identically switching to a second top-level `ShellContent` route, and navigating to a `Routing.RegisterRoute`-registered pushed route (a different navigation code path);
- **independent of the transition animation** — `GoToAsync(route, animate: false)` does not avoid it;
- **deterministic** — 100% reproduction, byte-for-byte identical native crash signature across every variant above;
- **reproduces on both .NET 10 (SDK 10.0.301, MAUI 10.0.90) and a full retarget to .NET 8 (SDK 8.0.422, MAUI 8.0.100)**;
- **reproduces on both a physical device and a freshly-created emulator image with no shared history** — same faulting binary, same crash offsets on both.
I have not found a workaround. Filing without one because the repro is minimal and the isolation work (13+ hypotheses eliminated) is unlikely to be reproduced independently by chance.
## Crash signature
Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
Faulting module: `libmonosgen-2.0.so`, BuildId `ee1bbe843f5a915776d1ac8cf10ad24aca4497bd` (matches the shipped binary).
Stable backtrace PC offsets across every reproduction on the .NET 10 build:
0x101310, 0xf647c, 0xc5f04, 0xc8548, 0xd2a8c, 0xcc964, 0x150aa4, 0x151798
Immediately preceded, every time, by:
monodroid-assembly: Could not load library '.../liblog'. dlopen failed: library "..." not found
monodroid-assembly: Could not load library 'liblog'. dlopen failed: library "liblog" not found
monodroid-assembly: Shared library 'liblog' not loaded, p/invoke '__android_log_print' may fail
(This warning alone is not the cause — it is present identically in the working Debug build.)
No managed exception is thrown; there is no Java stack. It is a purely native fault, occurring after the first page has already rendered (confirmed via app-level startup timing logs — the crash follows, not precedes, the first page appearing).
## Minimal repro
Stock `dotnet new maui` scaffold, Android target only, with two changes: a second `ShellContent` route added to `AppShell.xaml`, and the first page's `OnAppearing` triggering a navigation to it.
**AppShell.xaml:**
```xml
SecondPage.xaml — deliberately trivial, to show destination content doesn't matter:
MainPage.xaml.cs — trigger the second navigation automatically on appearing, no user interaction required to reproduce:
protected override async void OnAppearing()
{
base.OnAppearing();
await Task.Delay(500); // let the first page's frame actually paint
await Shell.Current.GoToAsync("//second");
// Also tested: Shell.Current.GoToAsync("//second", false) — same crash.
// Also tested: a Routing.RegisterRoute-registered pushed route instead
// of a second ShellContent, navigated to via a relative (non "//") route
// — same crash.
}
Steps:
dotnet publish -c Release -f net10.0-android -t:Run (physical device or emulator, either reproduces)
App launches, MainPage renders and appears
~0.5–1s later, the automatic navigation to SecondPage fires
Native SIGSEGV, app dies
Environment
Reproduced identically on both of the following:
Samsung Galaxy S22 Ultra (SM-S908E), Android 14, arm64-v8a, physical device
Google emulator image, Android 14 (API 34), google_apis system image, arm64-v8a, freshly created for this test, no customization, no shared history with the physical device
Host: macOS (Apple Silicon), dotnet CLI only (no IDE tooling, no Fast Deployment — Release build via dotnet publish only).
SDKs tested (same crash on both):
.NET SDK 10.0.301, MAUI workload 10.0.20/10.0.100 band, Microsoft.Maui.Controls 10.0.90
.NET SDK 8.0.422, MAUI workload 8.0.100/8.0.100, Microsoft.Maui.Controls 8.0.100
What I've ruled out
Each tested directly against the live crash, not assumed:
IL trimming (PublishTrimmed=false, AndroidLinkMode both None and Full)
AOT / LLVM (RunAOTCompilation=false, EnableLLVM=false)
JNI marshal methods (AndroidEnableMarshalMethods=false)
Packaging format (APK vs. AAB) and RID set (default multi-RID and pinned single android-arm64, which rules out the dotnet/android #10544-class DSO cache issue)
XAML inflator — MauiXamlInflator=SourceGen, the default XamlC, and a per-file Inflator="Runtime" override (verified genuinely applied via a diagnostic MSBuild target) — all three crash identically
Stale device/build state — fresh device reboot, and a from-scratch clone/copy of the entire project tree with clean obj/bin, produced byte-for-byte identical crash offsets
Runtime major version — full retarget from .NET 10 to .NET 8 (SDK, MAUI workload, and all transitive package versions changed together) — same defect persists
Physical device as a factor — identical crash on a stock, freshly-created emulator image
Destination page content and complexity — from a single Label up to a full page with real MVVM/DI/business-logic dependencies
First page complexity — from trivial up to a full real MSAL/DI dependency chain, always renders cleanly regardless
Navigation mechanism — ShellContent route switch vs. Routing.RegisterRoute pushed route, both crash identically
Transition animation — GoToAsync(route, animate: false) does not help
Sheer compiled app scale — a control inflated with 20 additional pages/view models (comparable count to a real production app) stayed clean; scale alone is not sufficient to trigger it
Questions for maintainers
- Do the PC offsets above (BuildId ee1bbe843f5a915776d1ac8cf10ad24aca4497bd) correspond to a known code path in Shell's Android page-transition/fragment handling?
- Is the liblog dlopen failure that always immediately precedes the crash diagnostic, or unrelated noise?
- Since both ShellContent-switch and pushed-route navigation crash identically, and disabling the transition animation doesn't help, is there a shared internal code path both mechanisms funnel through for constructing/attaching the Nth page that would explain why only the first page navigation is ever safe?
- Is there any known workaround for reaching a second page in Release without triggering this?
Happy to provide the full project, additional logcat captures, or run any diagnostic build on request.
Contributor guide
Research direction
Start with the minimal repro in AppShell.xaml and MainPage.xaml.cs, then run dotnet publish -c Release -f net10.0-android -t:Run on the stated Android targets. Compare the native backtrace and libmonosgen-2.0.so offsets while tracing the first Shell navigation and the alternate pushed-route path. Done means the Release build can navigate to a second page without the reproducible native SIGSEGV.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- android, csharp
- Domain
- mobile
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 38/100