stride3d/stride · error · FileNotFoundException
Could not find executable to start assembly
Error message
Could not find executable to start assembly [{assemblyLocation}] What it means
LoaderToolLocator.GetExecutable searches a set of candidate directories for the executable that corresponds to a given managed assembly location and returns the first path that exists. When none of the candidates exist on disk, it gives up with a FileNotFoundException naming the assembly. This signals that the tool's companion native/host executable is missing or not deployed alongside the assembly.
Solutions
- Verify the companion executable exists next to the assembly (same directory or expected subfolder) and restore/copy it.
- Rebuild or republish the tool so the host executable is included in the output (dotnet publish with the correct RID).
- Pass the correct assemblyLocation path that points at the deployed output, not a stale or moved location.
- Check that no antivirus/cleanup step deleted the executable after deployment.
Example fix
// before copy bin\Debug\MyTool.dll deploy\ // after dotnet publish MyTool -c Release -r win-x64 -o deploy\ # publishes exe + native loaders together
Defensive patterns
Strategy: try-catch
Validate before calling
var exeDir = Path.GetDirectoryName(assemblyLocation);
if (exeDir == null || !Directory.GetFiles(exeDir, "*").Any(f => f.EndsWith(".exe", StringComparison.OrdinalIgnoreCase) || f.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)))
throw new InvalidOperationException($"Deployment directory {exeDir} looks incomplete; refusing to locate loader tool."); Type guard
static bool IsDeployedToolPresent(string assemblyLocation) =>
File.Exists(assemblyLocation) &&
Directory.EnumerateFiles(Path.GetDirectoryName(assemblyLocation)!, "*")
.Any(f => f.EndsWith(".exe", StringComparison.OrdinalIgnoreCase)); Try / catch
try
{
var exe = LoaderToolLocator.GetExecutable(assemblyLocation);
}
catch (FileNotFoundException ex) when (ex.Message.Contains("Could not find executable to start assembly"))
{
logger.Error($"Tool executable missing for {assemblyLocation}; republish with 'dotnet publish -r <RID>'.");
throw;
} Prevention
- Always deploy with dotnet publish for the target RID instead of copying individual DLLs.
- Add a post-build smoke test that calls GetExecutable in CI so missing exes fail the build.
- Never move the assembly away from its native loaders/hosts after deployment.
When it happens
Trigger: Calling GetExecutable(assemblyLocation) when File.Exists() fails for every candidate path built from the assembly location (e.g. wrong build output directory, exe not copied to output, wrong runtime identifier folder).
Common situations: Running a tool from a partial publish output; moving the assembly exe away from its native loaders; switching RID/platform folders (e.g. win-x64 vs linux-x64) without redeploying; copying just the .dll without the .exe.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- Bundle could not be resolved
- Could not locate native executable
- Could not locate native library
- Package file [ ] was not found
- Cannot detect dependencies of projet
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/8475aebea224eaed.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shared/LoaderToolLocator/LoaderToolLocator.cs:60
var tfmPath = Path.GetDirectoryName(assemblyLocation);
if (tfmPath != null)
{
var parentPath = Path.GetDirectoryName(tfmPath);
if (parentPath != null && Path.GetFileName(parentPath).Equals("lib", StringComparison.Ordinal))
{
var packageRoot = Path.GetDirectoryName(parentPath);
if (packageRoot != null)
{
var tfm = Path.GetFileName(tfmPath);
var exeName = Path.GetFileNameWithoutExtension(assemblyLocation) + ExeExtension;
var exeLocation = Path.Combine(packageRoot, "tools", tfm, exeName);
if (File.Exists(exeLocation))
return exeLocation;
}
}
}
throw new FileNotFoundException($"Could not find executable to start assembly [{assemblyLocation}]");
}
}
}
View on GitHub (pinned to 96fad776d2)