stride3d/stride · error · InvalidOperationException

Failed to start .

Error message

Failed to start {CommandsPackageId} {version}.

What it means

After locating and launching the version-matched Stride.VisualStudio.Commands executable, Start calls Process.Start; if the OS returns null (the process could not be launched), this InvalidOperationException is thrown. Unlike the connection loop, this failure happens before any pipe retry logic and indicates the executable itself could not be spawned.

Solutions

  1. Confirm the mapped executable runs standalone: execute the path printed in the error manually and fix whatever blocks it (missing .NET runtime, unblock the file, adjust antivirus).
  2. Install the .NET runtime matching the framework folder the Commands package restored under (net10.0/net8.0/net6.0) for your OS and architecture.
  3. Re-restore the package after clearing caches ('dotnet nuget locals all --clear') in case the apphost binary is corrupt.
  4. Check OS security policies (AppLocker/Defender/quarantine) that silently prevent spawning the tool executable.

Example fix

// before (blocked/unlaunchable apphost)
C:\Users\me\.nuget\packages\stride.visualstudio.commands\4.1.0\...\Stride.VisualStudio.Commands.exe  <- returns null from Process.Start

// after (unblock and verify runtime)
Unblock-File .\Stride.VisualStudio.Commands.exe
dotnet --list-runtimes   # ensure the required runtime is installed
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify the mapped executable is launchable before spawning
var exe = LocateCommandsExecutable(version);
if (exe is null || !File.Exists(exe))
    throw new InvalidOperationException("Commands executable missing — check the NuGet restore first.");
if (!OperatingSystem.IsWindows())
    Console.Error.WriteLine("Commands host is Windows-targeted; Process.Start may fail on this OS.");

Type guard

static bool CanLaunch(string path) =>
    File.Exists(path) &&
    (OperatingSystem.IsWindows() || !(path.EndsWith(".exe", StringComparison.OrdinalIgnoreCase)));

Try / catch

try {
    using var gen = LegacyShaderCodeGenerator.Start(version);
    bytes = gen.Generate(shaderFile, shaderContent);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("Failed to start Stride.VisualStudio.Commands")) {
    Console.Error.WriteLine($"Tool spawn failed: {ex.Message}. Check installed .NET runtimes and AV policy.");
    return ExitCode.LaunchFailure;
}

Prevention

When it happens

Trigger: Process.Start(new ProcessStartInfo(executable, "--pipe=...") { UseShellExecute = false }) returns null — typically because the mapped executable path is not a launchable process image on the current OS/architecture.

Common situations: LoaderToolLocator mapped the restored assembly to a host not runnable on this machine (wrong architecture, e.g. x86 vs arm64, or a Windows-only host); antivirus or policy blocking execution of the downloaded tool; a net6.0/net8.0/net10.0 apphost whose matching runtime is absent so the launcher refuses to start it; file marked not-executable or blocked (Zone.Identifier) after download.

Related errors


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

Appendix: source

Thrown at sources/launcher/Stride.Cli/Legacy/LegacyShaderCodeGenerator.cs:46

        this.process = process;
        this.client = client;
    }

    /// <summary>Restores the version-matched Commands, spawns it, and connects. Caller owns the returned instance.</summary>
    public static LegacyShaderCodeGenerator Start(PackageVersion version)
    {
        var executable = LocateCommandsExecutable(version)
            ?? throw new InvalidOperationException($"Could not restore {CommandsPackageId} {version} (needed to regenerate shader code). Check your NuGet sources.");

        var address = "Stride/StrideCliShaders/" + Guid.NewGuid();
        var startInfo = new ProcessStartInfo(executable, $"--pipe=\"{address}\"")
        {
            UseShellExecute = false,
            CreateNoWindow = true,
            WorkingDirectory = Path.GetDirectoryName(executable)!,
        };
        var process = Process.Start(startInfo)
            ?? throw new InvalidOperationException($"Failed to start {CommandsPackageId} {version}.");

        // Stride 4.1 spoke ServiceWire 5.3.4 (BinaryFormatter, no compression); 4.2+ uses the modern default.
        var legacy = version.Version < new Version(4, 2);

        // The server needs a moment to open its named pipe; retry the connection briefly.
        for (var attempt = 0; ; attempt++)
        {
            try
            {
                var endpoint = new NpEndPoint(address + "/IStrideCommands");
                var client = legacy
                    ? new NpClient<IStrideCommands>(endpoint, new LegacyBinaryFormatterSerializer(), new LegacyDoNothingCompressor())
                    : new NpClient<IStrideCommands>(endpoint);
                return new LegacyShaderCodeGenerator(process, client);
            }
            catch when (attempt < 30 && !process.HasExited)
            {
                Thread.Sleep(100);

View on GitHub (pinned to 96fad776d2)