github/copilot-sdk · error · InvalidOperationException
Copilot runtime wrapper not found at
Error message
Copilot runtime wrapper not found at '{wrapper}'. What it means
ValidateRuntimePair checks that a Copilot runtime wrapper file exists before launching it. The wrapper executable (e.g. the Node script/entrypoint that loads runtime.node) was not found at the configured path, so launch is refused.
Solutions
- Verify the wrapper path in your options points to an existing file (use an absolute path).
- Reinstall/restore the Copilot runtime assets (nuget restore / package reinstall) so the wrapper is present.
- Check for typos, wrong casing, or pointing at a directory instead of the wrapper file.
- If the path is derived at runtime, resolve it relative to AppContext.BaseDirectory or the assembly location instead of the current working directory.
Example fix
// before options.WrapperPath = "copilot-runtime/wrapper.js"; // relative to CWD // after options.WrapperPath = Path.Combine(AppContext.BaseDirectory, "copilot-runtime", "wrapper.js");
Defensive patterns
Strategy: validation
Validate before calling
if (options.WrapperPath is null || !File.Exists(options.WrapperPath))
throw new FileNotFoundException($"Copilot runtime wrapper not found at '{options.WrapperPath}'"); Type guard
static bool WrapperExists(string? p) => p is { Length: > 0 } && File.Exists(p); Try / catch
try
{
await client.StartAsync();
}
catch (InvalidOperationException ex) when (ex.Message.Contains("wrapper not found"))
{
logger.LogError(ex, "Runtime wrapper missing at configured path");
} Prevention
- Use absolute paths built from AppContext.BaseDirectory for runtime assets.
- Verify runtime assets are included in build output and deployment artifacts.
- Reinstall the package after any partial copy or restore failure.
When it happens
Trigger: File.Exists(wrapper) is false at Client.cs:2502 when the client validates the runtime wrapper path during launch setup (ValidateRuntimePair), typically from a path supplied via CopilotClientOptions.
Common situations: Typo or wrong casing in the wrapper path in options; pointing at a directory instead of the wrapper file; the runtime assets were never downloaded/installed; the package was partially copied and the wrapper omitted; path computed relative to a working directory that differs at runtime.
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
- Copilot runtime wrapper at
- Could not determine directory for
- In-process FFI runtime library not found at
- Copilot CLI not found at
- Request cancelled by runtime
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/a59b846c9be97cb1.
Report an issue: GitHub.
Appendix: source
Thrown at dotnet/src/Client.cs:2502
var directory = Path.GetDirectoryName(searchedWrapper)!;
var runtimeNode = Path.Combine(directory, "runtime.node");
var explicitCliMarker = Path.Combine(directory, ExplicitBundledCliMarker);
if (!File.Exists(searchedWrapper)
&& !File.Exists(runtimeNode)
&& File.Exists(explicitCliMarker)
&& GetBundledCliPath(out _) is { } explicitCli)
{
return new RuntimeLaunch(explicitCli, "Bundled explicit CLI");
}
return ValidateRuntimePair(searchedWrapper, "Bundled runtime");
}
private static RuntimeLaunch ValidateRuntimePair(string wrapper, string source)
{
var runtimeNode = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(wrapper))!, "runtime.node");
if (!File.Exists(wrapper))
{
throw new InvalidOperationException($"Copilot runtime wrapper not found at '{wrapper}'.");
}
if (!File.Exists(runtimeNode))
{
throw new InvalidOperationException(
$"Copilot runtime wrapper at '{wrapper}' is missing its adjacent runtime.node at '{runtimeNode}'.");
}
if (new FileInfo(wrapper).Length == 0 || new FileInfo(runtimeNode).Length == 0)
{
throw new InvalidOperationException("Copilot runtime wrapper and adjacent runtime.node must both be non-empty.");
}
#if NET8_0_OR_GREATER
if (!OperatingSystem.IsWindows())
{
var mode = File.GetUnixFileMode(wrapper);
const UnixFileMode executeBits =
UnixFileMode.UserExecute | UnixFileMode.GroupExecute | UnixFileMode.OtherExecute;
if ((mode & executeBits) == 0)
{View on GitHub (pinned to cd8cf15dc3)