github/copilot-sdk · critical · InvalidOperationException
FFI runtime library is missing the
Error message
FFI runtime library is missing the '{export}' export. What it means
Bind<T> resolves a named export via NativeLoader.GetSymbol and throws when the symbol pointer is zero — the loaded library exists but does not export a required copilot_runtime_* function. This fails fast instead of producing a null-function-pointer crash later.
Solutions
- Reinstall the native runtime so its version matches the managed FfiRuntimeHost package.
- Verify the binary really is the copilot FFI runtime (export list via dumpbin/nm) and not another DLL.
- Align all deployment artifacts — never mix a new managed assembly with an old native lib.
- Pin both managed and native components to the same release in CI and deployment.
Example fix
// before Create(legacyRuntimePath); // lacks copilot_runtime_connection_write // after Create(versionMatchedRuntimePath); // exports all required symbols
Defensive patterns
Strategy: try-catch
Validate before calling
// pre-flight: load and probe exports before Create using var probe = NativeLibProbe.Open(libraryPath); foreach (var e in RequiredExports) if (!probe.HasExport(e)) throw new MissingExportException(e);
Try / catch
try { host = FfiRuntimeHost.Create(libraryPath); }
catch (InvalidOperationException ex) when (ex.Message.Contains("missing the '")) {
logger.LogError(ex, "Runtime library incompatible: {Msg}", ex.Message);
throw new ApplicationException("Native runtime version mismatch — reinstall matched runtime.", ex);
} Prevention
- Pin native library and managed package to the same release
- Validate exports after deployment upgrades
- Never mix old native binaries with new managed assemblies
- Record the native library version at startup for diagnostics
When it happens
Trigger: Loading a runtime library binary that is older/newer than the managed wrapper expects, so one of host_start, host_shutdown, connection_open, connection_write, etc. is absent.
Common situations: Version-skew between the managed dotnet package and a manually supplied native library; a stub or wrong binary placed at the library path; partially updated deployment replacing only one side.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- An in-process FFI runtime library is already loaded from
- An in-process FFI runtime library is already loaded from
- An in-process FFI runtime library is already loaded from
- copilot_runtime_connection_open failed.
- copilot_runtime_connection_open failed.
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/c4ac0bf1e9ab2187.
Report an issue: GitHub.
Appendix: source
Thrown at dotnet/src/FfiRuntimeHost.cs:453
throw new InvalidOperationException($"Failed to load FFI runtime library '{libraryPath}'.");
}
s_hostStart = Bind<HostStartDelegate>(handle, "copilot_runtime_host_start");
s_hostShutdown = Bind<HostShutdownDelegate>(handle, "copilot_runtime_host_shutdown");
s_connectionOpen = Bind<ConnectionOpenDelegate>(handle, "copilot_runtime_connection_open");
s_connectionWrite = Bind<ConnectionWriteDelegate>(handle, "copilot_runtime_connection_write");
s_connectionClose = Bind<ConnectionCloseDelegate>(handle, "copilot_runtime_connection_close");
s_loaded = true;
s_loadedPath = libraryPath;
}
}
private static T Bind<T>(IntPtr handle, string export) where T : Delegate
{
var symbol = NativeLoader.GetSymbol(handle, export);
if (symbol == IntPtr.Zero)
{
throw new InvalidOperationException($"FFI runtime library is missing the '{export}' export.");
}
return Marshal.GetDelegateForFunctionPointer<T>(symbol);
}
private static uint NativeHostStart(byte[] argvJson, byte[]? env) =>
s_hostStart!(argvJson, Len(argvJson.Length), env, env is null ? UIntPtr.Zero : Len(env.Length));
private uint NativeOpenConnection(uint serverId)
{
_outboundDelegate = OnOutbound;
return s_connectionOpen!(
serverId,
_outboundDelegate,
IntPtr.Zero,
null, UIntPtr.Zero,
null, UIntPtr.Zero,
null, UIntPtr.Zero);
}View on GitHub (pinned to cd8cf15dc3)