stride3d/stride · error · InvalidOperationException

Could not find a MSBuild installation (expected 16.0 or…

Error message

Could not find a MSBuild installation (expected 16.0 or later) Please ensure you have the .NET {NetMajorVersion} SDK installed from Microsoft's website

What it means

Thrown by FindAndSetMSBuildVersion when no suitable MSBuild installation can be located: for .NET Core it requires a DotNetSdk discovery whose major version matches NetMajorVersion; otherwise a VS 2019 (16.0+) setup or developer console install. The method must find MSBuild before the session can build projects.

Solutions

  1. Install the .NET SDK matching NetMajorVersion from Microsoft's website.
  2. Install Visual Studio 2019 or later with the .NET desktop development workload for VS-based discovery.
  3. Verify with 'dotnet --list-sdks' that the required major version is present and on PATH.
  4. Set DOTNET_ROOT/PATH so MSBuildLocator can discover the SDK.
  5. If a specific minor version matters, ensure it is installed rather than only a newer major.

Example fix

# before — no matching SDK
$ dotnet --list-sdks
3.1.426
# after — install the required SDK major version
$ dotnet --list-sdks
6.0.417
8.0.100
Defensive patterns

Strategy: fallback

Validate before calling

var instances = MSBuildLocator.QueryVisualStudioInstances().ToList();
bool hasRequired = instances.Any(i =>
    (i.DiscoveryType == DiscoveryType.DotNetSdk && i.Version.Major == netMajor) ||
    ((i.DiscoveryType == DiscoveryType.VisualStudioSetup || i.DiscoveryType == DiscoveryType.DeveloperConsole) && i.Version.Major >= 16));
if (!hasRequired) throw new InvalidOperationException($"Install .NET {netMajor} SDK or VS2019+.");

Try / catch

try { PackageSessionPublicHelper.FindAndSetMSBuildVersion(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("MSBuild installation"))
{
    // show install instructions / download link to the user
}

Prevention

When it happens

Trigger: Calling FindAndSetMSBuildVersion on a machine without the required .NET SDK version installed, or with only an older VS (pre-16.0) installation, or where MSBuildLocator cannot discover instances.

Common situations: CI/build agent without the .NET SDK; developer machine with only VS 2017; multiple .NET SDKs installed but none matching NetMajorVersion; SDK dotnet root not discoverable via PATH/DOTNET_ROOT.

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/489886a4f69efa1f. Report an issue: GitHub.

Appendix: source

Thrown at sources/assets/Stride.Core.Assets/PackageSessionPublicHelper.cs:47

    private static VisualStudioInstance? MSBuildInstance;

    /// <summary>
    /// This method finds a compatible version of MSBuild.
    /// </summary>
    public static void FindAndSetMSBuildVersion()
    {
        // Note: this should be called only once
        if (MSBuildInstance == null && Interlocked.Increment(ref MSBuildLocatorCount) == 1)
        {
            // Detect either .NET Core SDK or Visual Studio depending on current runtime
            var isNETCore = !RuntimeInformation.FrameworkDescription.StartsWith(".NET Framework", StringComparison.Ordinal);
            MSBuildInstance = MSBuildLocator.QueryVisualStudioInstances().FirstOrDefault(x => isNETCore
                ? x.DiscoveryType == DiscoveryType.DotNetSdk && x.Version.Major == NetMajorVersion
                : (x.DiscoveryType == DiscoveryType.VisualStudioSetup || x.DiscoveryType == DiscoveryType.DeveloperConsole) && x.Version.Major >= 16);

            if (MSBuildInstance == null)
            {
                throw new InvalidOperationException("Could not find a MSBuild installation (expected 16.0 or later) " +
                    $"Please ensure you have the .NET {NetMajorVersion} SDK installed from Microsoft's website");
            }

            // Make sure it is not already loaded (otherwise MSBuildLocator.RegisterDefaults() throws an exception)
            if (!AppDomain.CurrentDomain.GetAssemblies().Any(IsMSBuildAssembly))
            {
                // We can't use directly RegisterInstance because we want to avoid NuGet verison conflicts (between MSBuild/dotnet one and ours).
                // More details at https://github.com/microsoft/MSBuildLocator/issues/127
                // This code should be equivalent to MSBuildLocator.RegisterInstance(MSBuildInstance);
                //  except that we load everything in another context.

                ApplyDotNetSdkEnvironmentVariables(MSBuildInstance.MSBuildPath);

                var msbuildAssemblyLoadContext = new AssemblyLoadContext("MSBuild");

                // Fall back to the SDK directory for MSBuild assemblies. Runs after the NuGet resolver
                // (registered earlier) so Stride's pinned versions win over name-colliding SDK copies.
                AppDomain.CurrentDomain.AssemblyResolve += (_, resolveArgs) =>

View on GitHub (pinned to 96fad776d2)