github/copilot-sdk · error · IllegalStateException

An in-process FFI runtime library is already loaded from…

Error message

An in-process FFI runtime library is already loaded from ''; loading a different library from '' in the same process is not supported.

What it means

The class keeps a static loadedLib/loadedPath pair: only one native runtime library can be loaded per JVM process. Constructing a JnaNativeBinding with a different absolute path while a library is already loaded throws, because unloading JNA libraries is not possible and mixing runtimes would corrupt native state.

Solutions

  1. Reuse a single library path for the whole process (same cached runtime file).
  2. Reuse the existing JnaNativeBinding/FfiRuntimeHost instead of constructing a new one.
  3. Run tests needing different runtimes in separate JVMs (e.g. per-test fork).
  4. Restore the original runtime path configuration that was used on first load.

Example fix

// before
new JnaNativeBinding("/cache/runtime-v1/lib.so");
new JnaNativeBinding("/cache/runtime-v2/lib.so"); // throws
// after
NativeBindingHolder.getOrCreate("/cache/runtime-v2/lib.so"); // cached singleton per JVM
Defensive patterns

Strategy: type-guard

Validate before calling

if (NativeRuntimeRegistry.loadedPath != null && !NativeRuntimeRegistry.loadedPath.equals(requestedPath)) throw new IllegalStateException("different runtime already loaded");

Type guard

boolean canLoad(Path p) { return loadedPath == null || loadedPath.equals(p.toAbsolutePath().normalize()); }

Try / catch

try { binding = new JnaNativeBinding(path); } catch (IllegalStateException ex) { if (ex.getMessage().contains("already loaded")) { binding = existingSingleton; } else throw ex; }

Prevention

When it happens

Trigger: Creating a second FfiRuntimeHost/JnaNativeBinding pointing at a different library path (e.g. after a runtime upgrade, or tests using different extracted copies) within the same JVM.

Common situations: Test suites where one test pins an old runtime path and another uses a new one; hot-redeploy in a shared JVM; a config change altering the runtime directory between inits.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at java/sdk/src/main/java/com/github/copilot/ffi/JnaNativeBinding.java:207

     *            absolute path to the {@code runtime.node} native library
     * @throws IllegalStateException
     *             if a <em>different</em> library path has already been loaded in
     *             this JVM process
     */
    JnaNativeBinding(Path libraryPath) {
        Path absPath = libraryPath.toAbsolutePath().normalize();
        synchronized (LOAD_LOCK) {
            if (loadedLib == null) {
                LOG.fine(() -> "Loading native library from: " + absPath);
                try {
                    loadedLib = Native.load(absPath.toString(), CopilotRuntimeLibrary.class);
                } catch (UnsatisfiedLinkError e) {
                    throw new IllegalStateException("Failed to load native library from '" + absPath + "'", e);
                }
                loadedPath = absPath;
                LOG.fine(() -> "Native library loaded: " + absPath);
            } else if (!absPath.equals(loadedPath)) {
                throw new IllegalStateException("An in-process FFI runtime library is already loaded from '"
                        + loadedPath + "'; loading a different library from '" + absPath
                        + "' in the same process is not supported.");
            }
        }
        this.lib = loadedLib;
    }

    /**
     * Testing constructor — accepts a pre-built {@link CopilotRuntimeLibrary}
     * directly, bypassing disk I/O and the static singleton guard.
     *
     * <p>
     * This constructor is package-private and intended solely for unit tests.
     *
     * @param library
     *            a {@link CopilotRuntimeLibrary} stub or mock for testing
     */
    JnaNativeBinding(CopilotRuntimeLibrary library) {

View on GitHub (pinned to cd8cf15dc3)