MSBuildLoadContext.Load() causes FileLoadException for self-contained .NET apps loading MSBuild in-proc
Summary
A self-contained .NET 10 app that loads MSBuild in-process for project evaluation (a supported scenario) crashes with FileLoadException during SDK resolution. The issue is in MSBuildLoadContext.Load()'s final fallback, which loads assemblies into AssemblyLoadContext.Default instead of the custom ALC.
Bug details
MSBuildLoadContext.Load() has a final fallback that calls AssemblyLoadContext.Default.LoadFromAssemblyPath() with assemblies from BuildEnvironmentHelper.Instance.CurrentMSBuildToolsDirectory (the VS MSBuild bin directory):
// This is the problematic fallback:
string text3 = Path.Combine(
BuildEnvironmentHelper.Instance.CurrentMSBuildToolsDirectory,
assemblyName.Name + ".dll");
if (FileSystems.Default.FileExists(text3))
return AssemblyLoadContext.Default.LoadFromAssemblyPath(text3); // THROWS
When the Default ALC already has the same assembly loaded from the app's TPA with a different file version (e.g., System.Text.Json 10.0.0.0 from the .NET 10 runtime vs 10.0.0.2 from VS), Default.LoadFromAssemblyPath() throws FileLoadException because it refuses to load a different file for an already-loaded assembly.
Repro
Prerequisites: Windows with VS 18 Preview and .NET 10 SDK installed.
git clone https://github.com/AndyGerlicher/repro-net10resolver.git
cd repro-net10resolver
dotnet run
Expected: Project evaluation succeeds.
Actual: FileLoadException from MSBuildLoadContext during SDK resolution.
The repro project includes a workaround that patches WellKnownAssemblyNames to demonstrate this — once the conflicting assemblies are excluded from the fallback path, evaluation succeeds.
MSBuildLoadContext.Load()causesFileLoadExceptionfor self-contained .NET apps loading MSBuild in-procSummary
A self-contained .NET 10 app that loads MSBuild in-process for project evaluation (a supported scenario) crashes with
FileLoadExceptionduring SDK resolution. The issue is inMSBuildLoadContext.Load()'s final fallback, which loads assemblies intoAssemblyLoadContext.Defaultinstead of the custom ALC.Bug details
MSBuildLoadContext.Load()has a final fallback that callsAssemblyLoadContext.Default.LoadFromAssemblyPath()with assemblies fromBuildEnvironmentHelper.Instance.CurrentMSBuildToolsDirectory(the VS MSBuild bin directory):When the Default ALC already has the same assembly loaded from the app's TPA with a different file version (e.g.,
System.Text.Json10.0.0.0 from the .NET 10 runtime vs 10.0.0.2 from VS),Default.LoadFromAssemblyPath()throwsFileLoadExceptionbecause it refuses to load a different file for an already-loaded assembly.Repro
Prerequisites: Windows with VS 18 Preview and .NET 10 SDK installed.
git clone https://github.com/AndyGerlicher/repro-net10resolver.git cd repro-net10resolver dotnet runExpected: Project evaluation succeeds.
Actual:
FileLoadExceptionfromMSBuildLoadContextduring SDK resolution.The repro project includes a workaround that patches
WellKnownAssemblyNamesto demonstrate this — once the conflicting assemblies are excluded from the fallback path, evaluation succeeds.