Skip to content

Conversation

@jonathanpeppers
Copy link
Member

I was trying to run a dotnet new maui project in .NET 10 RC 2, which crashed with:

10-21 14:14:34.785 14069 14069 E AndroidRuntime: FATAL EXCEPTION: main
10-21 14:14:34.785 14069 14069 E AndroidRuntime: Process: com.companyname.hellomaui, PID: 14069
10-21 14:14:34.785 14069 14069 E AndroidRuntime: android.runtime.JavaProxyThrowable: [System.IndexOutOfRangeException]: Arg_IndexOutOfRangeException
10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at Microsoft.Maui.Hosting.AppHostBuilderExtensions+<>c.<ConfigureEnvironmentVariables>b__2_2 + 0x0(Unknown Source)
10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at System.Linq.Enumerable.ToDictionary + 0x8c(Unknown Source)
10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at System.Linq.Enumerable.ToDictionary + 0x0(Unknown Source)
10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at Microsoft.Maui.Hosting.AppHostBuilderExtensions.ConfigureEnvironmentVariables + 0x5a(Unknown Source)
10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at Microsoft.Maui.Hosting.MauiAppBuilder..ctor + 0x12e(Unknown Source)
10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at Microsoft.Maui.Hosting.MauiApp.CreateBuilder + 0x0(Unknown Source)
10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at hellomaui.MauiProgram.CreateMauiApp + 0x0(Unknown Source)
10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at hellomaui.MainApplication.CreateMauiApp + 0x0(Unknown Source)
10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at Microsoft.Maui.MauiApplication.OnCreate + 0xb(Unknown Source)
10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at Android.App.Application.n_OnCreate + 0x16(Unknown Source)
10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at crc6488302ad6e9e4df1a.MauiApplication.n_onCreate(Native Method)
10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at crc6488302ad6e9e4df1a.MauiApplication.onCreate(MauiApplication.java:17)
10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1381)
10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7830)
10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at android.app.ActivityThread.-$$Nest$mhandleBindApplication(Unknown Source:0)
10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2546)
10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at android.os.Handler.dispatchMessage(Handler.java:110)
10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at android.os.Looper.loopOnce(Looper.java:248)
10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at android.os.Looper.loop(Looper.java:338)
10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at android.app.ActivityThread.main(ActivityThread.java:9067)
10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at java.lang.reflect.Method.invoke(Native Method)
10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:593)
10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:932)

I reviewed the existing code:

var envVarLines = System.IO.File.ReadAllLines(androidEnvVarFilePath);
var fileEnvironmentVariables = envVarLines
.Select(line => line.Split('=', 2))
.ToDictionary(parts => parts[0], parts => parts[1]);

Which made me look at the contents of:

> adb pull /data/local/tmp/ide-launchenv.txt
/data/local/tmp/ide-launchenv.txt: 1 file pulled, 0 skipped. 0.0 MB/s (3 bytes in 0.002s)

The file contains a line with a space character two newlines. No idea what put that there?!?

I think the Select(line => line.Split('=', 2)) call is problematic, in addition to the ToDictionary() call. I think both of these could throw exceptions on malformed / weird files.

I also got "nerd sniped" to improve the performance:

  • System.IO.File.ReadAllLines() allocates a string[]

  • line.Split('=', 2) allocates a string[]

  • ToDictionary(...) allocates a dictionary and enumerates everything again.

We can just flatten the System.Linq usage here into a foreach loop and avoid those allocations. We can also use IndexOf('=') to find the split point.

After these changes, the app no longer crashes and starts up fine.

I was trying to run a `dotnet new maui` project in .NET 10 RC 2, which
crashed with:

    10-21 14:14:34.785 14069 14069 E AndroidRuntime: FATAL EXCEPTION: main
    10-21 14:14:34.785 14069 14069 E AndroidRuntime: Process: com.companyname.hellomaui, PID: 14069
    10-21 14:14:34.785 14069 14069 E AndroidRuntime: android.runtime.JavaProxyThrowable: [System.IndexOutOfRangeException]: Arg_IndexOutOfRangeException
    10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at Microsoft.Maui.Hosting.AppHostBuilderExtensions+<>c.<ConfigureEnvironmentVariables>b__2_2 + 0x0(Unknown Source)
    10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at System.Linq.Enumerable.ToDictionary + 0x8c(Unknown Source)
    10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at System.Linq.Enumerable.ToDictionary + 0x0(Unknown Source)
    10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at Microsoft.Maui.Hosting.AppHostBuilderExtensions.ConfigureEnvironmentVariables + 0x5a(Unknown Source)
    10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at Microsoft.Maui.Hosting.MauiAppBuilder..ctor + 0x12e(Unknown Source)
    10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at Microsoft.Maui.Hosting.MauiApp.CreateBuilder + 0x0(Unknown Source)
    10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at hellomaui.MauiProgram.CreateMauiApp + 0x0(Unknown Source)
    10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at hellomaui.MainApplication.CreateMauiApp + 0x0(Unknown Source)
    10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at Microsoft.Maui.MauiApplication.OnCreate + 0xb(Unknown Source)
    10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at Android.App.Application.n_OnCreate + 0x16(Unknown Source)
    10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at crc6488302ad6e9e4df1a.MauiApplication.n_onCreate(Native Method)
    10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at crc6488302ad6e9e4df1a.MauiApplication.onCreate(MauiApplication.java:17)
    10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1381)
    10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7830)
    10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at android.app.ActivityThread.-$$Nest$mhandleBindApplication(Unknown Source:0)
    10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2546)
    10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at android.os.Handler.dispatchMessage(Handler.java:110)
    10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at android.os.Looper.loopOnce(Looper.java:248)
    10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at android.os.Looper.loop(Looper.java:338)
    10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at android.app.ActivityThread.main(ActivityThread.java:9067)
    10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at java.lang.reflect.Method.invoke(Native Method)
    10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:593)
    10-21 14:14:34.785 14069 14069 E AndroidRuntime: 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:932)

Reviewing the existing code:

https://github.com/dotnet/maui/blob/a4c124661c1e3c2f530ff2d4ec4c0a86eda8fcbb/src/Core/src/Hosting/Dispatching/AppHostBuilderExtensions.cs#L53-L57

So, I looked at the contents of:

    > adb pull /data/local/tmp/ide-launchenv.txt
    /data/local/tmp/ide-launchenv.txt: 1 file pulled, 0 skipped. 0.0 MB/s (3 bytes in 0.002s)

The file contains a line with a space character and a newline. No idea
what put that there?!?

I think the `Select(line => line.Split('=', 2))` call is problematic,
in addition to the `ToDictionary()` call. I think both of these could
throw exceptions on malformed / weird files.

I also got "nerd sniped" to improve the performance:

* `System.IO.File.ReadAllLines()` allocates a `string[]`

* `line.Split('=', 2)` allocates a `string[]`

* `ToDictionary(...)` allocates a dictionary and enumerates
  everything again.

We can just flatten the System.Linq usage here into a `foreach` loop
and avoid those allocations. We can also use `IndexOf('=')` to find
the split point.

After these changes, the app no longer crashes and starts up fine.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR fixes a crash in Android MAUI applications caused by malformed environment variable files and improves performance by reducing allocations. The issue occurred when the ide-launchenv.txt file contained invalid entries (empty lines or lines without '=' delimiters), causing IndexOutOfRangeException during app startup.

Key Changes:

  • Replaced LINQ-based parsing with a manual foreach loop to handle malformed input gracefully
  • Added validation to skip invalid lines (empty lines or lines without '=' delimiter)
  • Improved performance by eliminating intermediate array and dictionary allocations

Comment on lines +55 to +61
int index = line.IndexOf('=', StringComparison.Ordinal);
if (index > 0)
{
string key = line.Substring(0, index);
string value = line.Substring(index + 1); // May be empty for values like "KEY="
environmentVariables[key] = value;
}
Copy link
Member Author

Choose a reason for hiding this comment

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

I didn't see a good way to write a test, @jfversluis can you check that Aspire still works with this change?

@jonathanpeppers jonathanpeppers added this to the .NET 10.0 GA milestone Oct 21, 2025
@PureWeen
Copy link
Member

/backport to release/10.0.1xx

@github-actions
Copy link
Contributor

Started backporting to release/10.0.1xx: https://github.com/dotnet/maui/actions/runs/18696186487

@PureWeen PureWeen added the p/0 Work that we can't release without label Oct 21, 2025
@PureWeen PureWeen moved this from Todo to Ready To Review in MAUI SDK Ongoing Oct 21, 2025
@jonathanpeppers
Copy link
Member Author

@github-project-automation github-project-automation bot moved this from Ready To Review to Done in MAUI SDK Ongoing Oct 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

p/0 Work that we can't release without

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants