Skip to content

Conversation

@jonathanpeppers
Copy link
Member

When running on a platform like Android, startup hooks can run via .NET's runtimeconfig.json, such as:

<ItemGroup>
  <RuntimeHostConfigurationOption Include="STARTUP_HOOKS" Value="Microsoft.Extensions.DotNetDeltaApplier" />
</ItemGroup>

If done this way, $DOTNET_STARTUP_HOOKS can be null, leading to:

01-08 16:07:49.336 14598 14598 F mono-rt :  System.NullReferenceException: Object reference not set to an instance of an object.
01-08 16:07:49.336 14598 14598 F mono-rt :    at Microsoft.DotNet.HotReload.HotReloadAgent.RemoveCurrentAssembly(Type startupHookType, String environment)
01-08 16:07:49.336 14598 14598 F mono-rt :    at Microsoft.DotNet.HotReload.HotReloadAgent.ClearHotReloadEnvironmentVariables(Type startupHookType)
01-08 16:07:49.336 14598 14598 F mono-rt :    at StartupHook.Initialize()
01-08 16:07:49.336 14598 14598 F mono-rt :    at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
01-08 16:07:49.336 14598 14598 F mono-rt :    at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
01-08 16:07:49.336 14598 14598 F mono-rt :    --- End of inner exception stack trace ---
01-08 16:07:49.336 14598 14598 F mono-rt :    at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
01-08 16:07:49.336 14598 14598 F mono-rt :    at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
01-08 16:07:49.336 14598 14598 F mono-rt :    at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
01-08 16:07:49.336 14598 14598 F mono-rt :    at System.StartupHookProvider.CallStartupHook(StartupHookNameOrPath startupHook)
01-08 16:07:49.336 14598 14598 F mono-rt :    at System.StartupHookProvider.ProcessStartupHooks(String diagnosticStartupHooks)

I think we should remove the ! and do a better null check, to just prevent this from happening.

I don't know yet if we'll use the env var or the runtimeconfig.json by default, but this seems reasonable to fix.

With the fix, it makes it to an expected state:

01-08 16:20:20.560 17468 17468 I DOTNET  : [HotReload] Environment variable DOTNET_WATCH_HOTRELOAD_NAMEDPIPE_NAME has no value

When running on a platform like Android, startup hooks can run via
.NET's `runtimeconfig.json`, such as:

    <ItemGroup>
      <RuntimeHostConfigurationOption Include="STARTUP_HOOKS" Value="Microsoft.Extensions.DotNetDeltaApplier" />
    </ItemGroup>

If done this way, `$DOTNET_STARTUP_HOOKS` can be `null`, leading to:

    01-08 16:07:49.336 14598 14598 F mono-rt :  System.NullReferenceException: Object reference not set to an instance of an object.
    01-08 16:07:49.336 14598 14598 F mono-rt :    at Microsoft.DotNet.HotReload.HotReloadAgent.RemoveCurrentAssembly(Type startupHookType, String environment)
    01-08 16:07:49.336 14598 14598 F mono-rt :    at Microsoft.DotNet.HotReload.HotReloadAgent.ClearHotReloadEnvironmentVariables(Type startupHookType)
    01-08 16:07:49.336 14598 14598 F mono-rt :    at StartupHook.Initialize()
    01-08 16:07:49.336 14598 14598 F mono-rt :    at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
    01-08 16:07:49.336 14598 14598 F mono-rt :    at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
    01-08 16:07:49.336 14598 14598 F mono-rt :    --- End of inner exception stack trace ---
    01-08 16:07:49.336 14598 14598 F mono-rt :    at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
    01-08 16:07:49.336 14598 14598 F mono-rt :    at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
    01-08 16:07:49.336 14598 14598 F mono-rt :    at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
    01-08 16:07:49.336 14598 14598 F mono-rt :    at System.StartupHookProvider.CallStartupHook(StartupHookNameOrPath startupHook)
    01-08 16:07:49.336 14598 14598 F mono-rt :    at System.StartupHookProvider.ProcessStartupHooks(String diagnosticStartupHooks)

I think we should remove the `!` and do a better null check, to just
prevent this from happening.

I don't know yet if we'll use the env var or the `runtimeconfig.json`
by default, but this seems reasonable to fix.

With the fix, it makes it to an expected state:

    01-08 16:20:20.560 17468 17468 I DOTNET  : [HotReload] Environment variable DOTNET_WATCH_HOTRELOAD_NAMEDPIPE_NAME has no value
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 NullReferenceException in the HotReloadAgent that occurs on platforms like Android where startup hooks can be configured via runtimeconfig.json instead of environment variables, resulting in a null DOTNET_STARTUP_HOOKS variable.

Key changes:

  • Remove null-forgiving operator when retrieving environment variable
  • Update RemoveCurrentAssembly to accept nullable string parameter
  • Use string.IsNullOrEmpty() for more robust null/empty checking

@jonathanpeppers jonathanpeppers enabled auto-merge (squash) January 10, 2026 14:17
@jonathanpeppers jonathanpeppers merged commit 51a741c into release/10.0.2xx Jan 10, 2026
26 checks passed
@jonathanpeppers jonathanpeppers deleted the dev/peppers/HotReloadAgentNRE branch January 10, 2026 15:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants