{"record":{"id":"5d9e75eeaff1a7d9","repo":"github/copilot-sdk","slug":"ffi-runtime-library-not-found-looked-for-flatli","errorCode":null,"errorMessage":"FFI runtime library not found. Looked for '{flatLibraryPath}', '{adjacentPrebuildPath}', and '{prebuildsLibraryPath}'.","messagePattern":"FFI runtime library not found\\. Looked for '(.+?)', '(.+?)', and '(.+?)'\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"dotnet/src/Client.cs","lineNumber":2573,"sourceCode":"        var fullEntrypoint = Path.GetFullPath(cliPath);\n        var directory = Path.GetDirectoryName(fullEntrypoint)\n            ?? throw new InvalidOperationException($\"Could not determine directory for '{cliPath}'.\");\n        var flatLibraryPath = Path.GetFullPath(\n            $\"{directory}{Path.DirectorySeparatorChar}{FfiRuntimeHost.GetRuntimeLibraryFileName()}\");\n        if (File.Exists(flatLibraryPath))\n        {\n            return flatLibraryPath;\n        }\n        var adjacentPrebuildPath = Path.Combine(directory, \"runtime.node\");\n        if (File.Exists(adjacentPrebuildPath))\n        {\n            return adjacentPrebuildPath;\n        }\n        var prebuildsLibraryPath = Path.Combine(\n            directory, \"prebuilds\", GetNapiPrebuildsFolderOrThrow(), \"runtime.node\");\n        return File.Exists(prebuildsLibraryPath)\n            ? prebuildsLibraryPath\n            : throw new InvalidOperationException(\n                $\"FFI runtime library not found. Looked for '{flatLibraryPath}', '{adjacentPrebuildPath}', and '{prebuildsLibraryPath}'.\");\n    }\n\n    /// <summary>\n    /// Returns the napi-rs prebuilds folder name for the current host — the\n    /// <c>&lt;node-platform&gt;-&lt;arch&gt;</c> convention (e.g. <c>win32-x64</c>,\n    /// <c>darwin-arm64</c>, <c>linux-x64</c>) under which the runtime ships\n    /// <c>prebuilds/&lt;folder&gt;/runtime.node</c>. This differs from the .NET RID\n    /// (<c>win-x64</c>/<c>osx-x64</c>) for Windows and macOS.\n    /// </summary>\n    private static string? GetNapiPrebuildsFolder()\n    {\n        string platform;\n        if (OperatingSystem.IsWindows()) platform = \"win32\";\n        else if (OperatingSystem.IsLinux())\n        {\n            platform = RuntimeInformation.RuntimeIdentifier.StartsWith(\"linux-musl-\", StringComparison.Ordinal)\n                ? \"linuxmusl\"","sourceCodeStart":2555,"sourceCodeEnd":2591,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/dotnet/src/Client.cs#L2555-L2591","documentation":"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.","triggerScenarios":"Starting the client with FFI runtime hosting when none of flatLibraryPath, adjacentPrebuildPath, or prebuildsLibraryPath exist on disk (GetFFILibraryPath-style resolution returned no match).","commonSituations":"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).","solutions":["Reinstall/upgrade the Copilot SDK package so the native FFI runtime (runtime.node) is restored into the output directory or prebuilds folder.","Verify the file actually exists at one of the three printed paths; manually copy runtime.node into prebuilds/<platform>-<arch>/ if it was stripped.","Ensure your publish/CI pipeline does not exclude native assets (check csproj Content/None Include rules and dotnet publish trimming settings).","Confirm the host platform/arch matches an available napi-rs prebuild; fall back to stdio/CLI hosting if FFI hosting is unavailable."],"exampleFix":"// before: assumes FFI runtime is present\ncopilot = new CopilotClient(); // InvalidOperationException at startup\n\n// after: ensure native asset is copied, or fall back to stdio\nif (!File.Exists(Path.Combine(AppContext.BaseDirectory, \"prebuilds\", \"linux-x64\", \"runtime.node\")))\n{\n    // use a runtime mode that spawns the CLI process instead of FFI hosting\n    copilot = new CopilotClient(useStdio: true);\n}","handlingStrategy":"fallback","validationCode":"var prebuilds = Path.Combine(AppContext.BaseDirectory, \"prebuilds\", \"linux-x64\", \"runtime.node\");\nif (!File.Exists(prebuilds))\n    throw new InvalidOperationException(\"FFI runtime missing; use stdio mode\");","typeGuard":null,"tryCatchPattern":"try { client = new CopilotClient(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"FFI runtime library not found\"))\n{ client = new CopilotClient(useStdio: true); }","preventionTips":["Verify runtime.node exists in the output dir after restore/publish in CI","Do not strip native assets with publish trimming rules","Pin the SDK package version so prebuilds match your platform"],"tags":["ffi","native-library","startup","dotnet"],"backgroundTag":"file-not-found","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}