github/copilot-sdk · error · IllegalStateException

FfiRuntimeHost is already closed.

Error message

FfiRuntimeHost is already closed.

What it means

FfiRuntimeHost.start() throws this IllegalStateException when the host has already been disposed (disposed flag set) and cannot be started again. A closed FfiRuntimeHost is terminal; a new instance must be created to serve another in-process runtime.

Solutions

  1. Create a new FfiRuntimeHost instance instead of calling start on a disposed one
  2. Track host state in your application and rebuild the host after any close
  3. Avoid closing the host for transient restarts; only close at full application shutdown
  4. Check disposed state before start (or catch IllegalStateException) and re-create the host in the recovery path

Example fix

// before
host.close();
host.start(entrypoint, options); // IllegalState
// after
host.close();
host = new FfiRuntimeHost(nativeBinding);
host.start(entrypoint, options);
Defensive patterns

Strategy: validation

Validate before calling

// track disposal yourself; FfiRuntimeHost.disposed is internal
if (hostRef.get() == null || hostClosed) {
    hostRef.set(new FfiRuntimeHost(nativeBinding));
}
FfiRuntimeHost host = hostRef.get();

Try / catch

try {
    host.start(entrypoint, options);
} catch (IllegalStateException e) {
    if (String.valueOf(e.getMessage()).contains("already closed")) {
        host = new FfiRuntimeHost(nativeBinding);
        host.start(entrypoint, options);
    } else throw e;
}

Prevention

When it happens

Trigger: Calling start(entrypointPath, options) on an FfiRuntimeHost instance after close()/dispose completed — e.g., restarting the runtime by re-calling start on the same object instead of constructing a fresh host.

Common situations: Restart-after-shutdown logic that reuses the host reference; lifecycle bugs in tests or apps where close() runs in a finally and start() is later called for the next operation; DI containers caching a disposed host singleton.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at java/sdk/src/main/java/com/github/copilot/ffi/FfiRuntimeHost.java:100

    private static Path resolveLibraryPath() throws IOException {
        return NativeRuntimeLoader.resolve();
    }

    /**
     * Starts the in-process runtime and opens a connection.
     *
     * @param entrypointPath
     *            optional explicit legacy CLI entrypoint passed in
     *            {@code argv_json}
     * @param options
     *            client options used to construct {@code argv_json} and
     *            {@code env_json}
     */
    public void start(String entrypointPath, CopilotClientOptions options) {
        Objects.requireNonNull(options, "options must not be null");
        if (disposed.get()) {
            throw new IllegalStateException("FfiRuntimeHost is already closed.");
        }
        if (serverId.get() != 0 || connectionId.get() != 0) {
            throw new IllegalStateException("FfiRuntimeHost has already been started.");
        }

        byte[] argvJson = buildArgvJson(entrypointPath, options);
        byte[] envJson = buildEnvJson(options);
        int hostHandle = runHostStartOnBlockingThread(argvJson, envJson);
        if (hostHandle == 0) {
            String lib = libraryPath != null ? libraryPath : "<unknown>";
            throw new IllegalStateException("copilot_runtime_host_start failed (library '" + lib + "').");
        }

        // Hold operationLock while publishing handles to serialize with close().
        // Recheck disposed in case close() ran while hostStart was blocking.
        operationLock.lock();
        try {
            if (disposed.get()) {

View on GitHub (pinned to cd8cf15dc3)