.NET MAUI
iOS
Mobile Development

MAUI iOS App Crashing Instantly in Release Mode

September 10, 2024Max Mannstein

The Problem

This is a classic issue that almost every .NET MAUI developer runs into sooner or later. Your app works perfectly in Debug mode, but the moment you switch to Release and deploy to a real device, it crashes instantly on launch.

If you've recently updated your NuGet packages, the chances are even higher that you'll encounter this.

The Cause

In 99.9% of cases, this is caused by AOT (Ahead-of-Time) compilation for iOS in MAUI. Here's what's happening:

  • In Debug mode, .NET MAUI uses JIT (Just-in-Time) compilation, which compiles code on the fly as it runs.
  • In Release mode, iOS requires AOT compilation, which compiles everything ahead of time into native code.

The problem is that some NuGet packages don't fully support AOT compilation. They may rely on reflection, dynamic code generation, or other patterns that work fine with JIT but break under AOT. From my experience, using generics extensively can sometimes trigger this issue as well.

The Fixes

There are three approaches to solve this, each with its own trade-offs.

Fix 1: Enabling the Interpreter

This is the quickest fix and works in virtually all cases. It enables JIT compilation for iOS, which makes AOT-related problems disappear entirely.

The downside is that you take a significant performance hit on iOS. For this reason, I consider it more of an emergency solution — useful when you need to release quickly, but not ideal for production long-term.

Open your .csproj file and add:

<PropertyGroup Condition="$(TargetFramework.Contains('-ios')) and '$(Configuration)' == 'Release'">
    <UseInterpreter>true</UseInterpreter>
</PropertyGroup>

Then rebuild your app.

Fix 2: Enabling the MtouchInterpreter

This is a less aggressive alternative to the full interpreter. In my experience, the performance impact is noticeably smaller, though I can't say for certain whether that's universally true.

The catch is that it doesn't solve every AOT issue. I've had success using this specifically with packages like LiteDB, but I've also run into cases where it wasn't enough.

Open your .csproj file and add:

<PropertyGroup Condition="$(TargetFramework.Contains('-ios')) and '$(Configuration)' == 'Release'">
    <MtouchInterpreter>-all</MtouchInterpreter>
</PropertyGroup>

Then rebuild your app.

For more details, see the official Microsoft documentation: Mono interpreter on iOS and Mac Catalyst - .NET MAUI

Fix 3: Finding and Fixing the Problematic NuGet Package

This approach takes more time but gives you the best performance since you're addressing the root cause instead of working around it. After dealing with this issue multiple times, I've developed a reliable strategy for tracking down the offending package.

Here's how to do it:

  1. Connect your iPhone to your Mac via cable
  2. Open the Console app on your Mac (Console User Guide)
  3. Select your phone in the sidebar and click Start Streaming
  4. Launch the crashing app on your phone
  5. Search for the error in the Console output — it will tell you which assembly or NuGet package is causing the AOT issue
  6. Downgrade or upgrade the problematic package to a version that supports AOT correctly

One important note: the Console app receives a huge amount of messages per second from your phone. You need to look carefully and use the search/filter functionality to find the relevant error messages for your app.

Recommendation

My recommended approach is:

  • If you need to ship immediately: Use Fix 1 (full interpreter) to unblock your release
  • After release: Take the time to apply Fix 3 — find the exact package causing the issue and resolve it properly
  • Fix 2 is a good middle ground if you know the specific package and it works with the MtouchInterpreter

In my experience, AOT issues tend to resurface every time you update NuGet packages after a longer period. Having this debugging workflow ready saves a lot of time.