github/copilot-sdk · error · InvalidOperationException

FFI runtime library not found. Looked for

Error message

FFI runtime library not found. Looked for '{flatLibraryPath}', '{adjacentPrebuildPath}', and '{prebuildsLibraryPath}'.

What it means

CopilotClient needs the native FFI runtime library (`runtime.node`) to host the CLI in-process. It probes three well-known locations — a flat path, an adjacent `prebuilds` path, and the napi-rs `prebuilds/<platform>-<arch>/` layout — and throws InvalidOperationException when none exists. This means the native runtime binary was never installed or is laid out for a different platform/arch.

Solutions

  1. Reinstall/upgrade the Copilot SDK package so the native FFI runtime (runtime.node) is restored into the output directory or prebuilds folder.
  2. Verify the file actually exists at one of the three printed paths; manually copy runtime.node into prebuilds/<platform>-<arch>/ if it was stripped.
  3. Ensure your publish/CI pipeline does not exclude native assets (check csproj Content/None Include rules and dotnet publish trimming settings).
  4. Confirm the host platform/arch matches an available napi-rs prebuild; fall back to stdio/CLI hosting if FFI hosting is unavailable.

Example fix

// before: assumes FFI runtime is present
copilot = new CopilotClient(); // InvalidOperationException at startup

// after: ensure native asset is copied, or fall back to stdio
if (!File.Exists(Path.Combine(AppContext.BaseDirectory, "prebuilds", "linux-x64", "runtime.node")))
{
    // use a runtime mode that spawns the CLI process instead of FFI hosting
    copilot = new CopilotClient(useStdio: true);
}
Defensive patterns

Strategy: fallback

Validate before calling

var prebuilds = Path.Combine(AppContext.BaseDirectory, "prebuilds", "linux-x64", "runtime.node");
if (!File.Exists(prebuilds))
    throw new InvalidOperationException("FFI runtime missing; use stdio mode");

Try / catch

try { client = new CopilotClient(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("FFI runtime library not found"))
{ client = new CopilotClient(useStdio: true); }

Prevention

When it happens

Trigger: Starting the client with FFI runtime hosting when none of flatLibraryPath, adjacentPrebuildPath, or prebuildsLibraryPath exist on disk (GetFFILibraryPath-style resolution returned no match).

Common situations: NuGet package installed without the native runtime asset included; publishing/trimming a .NET app that drops the runtime.node content file; downloading a prebuilt binary for the wrong OS/arch; running on a platform napi-rs does not ship prebuilds for (e.g. linux-musl variants).

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


AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09). Data as JSON: /api/errors/5d9e75eeaff1a7d9. Report an issue: GitHub.

Appendix: source

Thrown at dotnet/src/Client.cs:2573

        var fullEntrypoint = Path.GetFullPath(cliPath);
        var directory = Path.GetDirectoryName(fullEntrypoint)
            ?? throw new InvalidOperationException($"Could not determine directory for '{cliPath}'.");
        var flatLibraryPath = Path.GetFullPath(
            $"{directory}{Path.DirectorySeparatorChar}{FfiRuntimeHost.GetRuntimeLibraryFileName()}");
        if (File.Exists(flatLibraryPath))
        {
            return flatLibraryPath;
        }
        var adjacentPrebuildPath = Path.Combine(directory, "runtime.node");
        if (File.Exists(adjacentPrebuildPath))
        {
            return adjacentPrebuildPath;
        }
        var prebuildsLibraryPath = Path.Combine(
            directory, "prebuilds", GetNapiPrebuildsFolderOrThrow(), "runtime.node");
        return File.Exists(prebuildsLibraryPath)
            ? prebuildsLibraryPath
            : throw new InvalidOperationException(
                $"FFI runtime library not found. Looked for '{flatLibraryPath}', '{adjacentPrebuildPath}', and '{prebuildsLibraryPath}'.");
    }

    /// <summary>
    /// Returns the napi-rs prebuilds folder name for the current host — the
    /// <c>&lt;node-platform&gt;-&lt;arch&gt;</c> convention (e.g. <c>win32-x64</c>,
    /// <c>darwin-arm64</c>, <c>linux-x64</c>) under which the runtime ships
    /// <c>prebuilds/&lt;folder&gt;/runtime.node</c>. This differs from the .NET RID
    /// (<c>win-x64</c>/<c>osx-x64</c>) for Windows and macOS.
    /// </summary>
    private static string? GetNapiPrebuildsFolder()
    {
        string platform;
        if (OperatingSystem.IsWindows()) platform = "win32";
        else if (OperatingSystem.IsLinux())
        {
            platform = RuntimeInformation.RuntimeIdentifier.StartsWith("linux-musl-", StringComparison.Ordinal)
                ? "linuxmusl"

View on GitHub (pinned to cd8cf15dc3)