{"record":{"id":"9abb92a2e69edb2e","repo":"github/copilot-sdk","slug":"ffiruntimehost-was-closed-during-startup","errorCode":null,"errorMessage":"FfiRuntimeHost was closed during startup.","messagePattern":"FfiRuntimeHost was closed during startup\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"java/sdk/src/main/java/com/github/copilot/ffi/FfiRuntimeHost.java","lineNumber":124,"sourceCode":"        byte[] argvJson = buildArgvJson(entrypointPath, options);\n        byte[] envJson = buildEnvJson(options);\n        int hostHandle = runHostStartOnBlockingThread(argvJson, envJson);\n        if (hostHandle == 0) {\n            String lib = libraryPath != null ? libraryPath : \"<unknown>\";\n            throw new IllegalStateException(\"copilot_runtime_host_start failed (library '\" + lib + \"').\");\n        }\n\n        // Hold operationLock while publishing handles to serialize with close().\n        // Recheck disposed in case close() ran while hostStart was blocking.\n        operationLock.lock();\n        try {\n            if (disposed.get()) {\n                try {\n                    nativeBinding.hostShutdown(hostHandle);\n                } catch (Throwable ignored) {\n                    // Best effort\n                }\n                throw new IllegalStateException(\"FfiRuntimeHost was closed during startup.\");\n            }\n            serverId.set(hostHandle);\n\n            OutboundCallback callback = createOutboundCallback();\n            callbackRef = callback;\n            int connHandle = nativeBinding.connectionOpen(hostHandle, callback, Pointer.NULL, null, 0, null, 0, null,\n                    0);\n            if (connHandle == 0) {\n                try {\n                    nativeBinding.hostShutdown(hostHandle);\n                } catch (Throwable ignored) {\n                    // Best effort\n                }\n                serverId.set(0);\n                callbackRef = null;\n                throw new IllegalStateException(\"copilot_runtime_connection_open failed.\");\n            }\n            connectionId.set(connHandle);","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/java/sdk/src/main/java/com/github/copilot/ffi/FfiRuntimeHost.java#L106-L142","documentation":"After the native host started, start() re-checks the disposed flag while holding operationLock. If close() ran concurrently while hostStart was blocking, the library shuts down the just-created native host (best effort) and throws, because publishing handles into a closed host would leak them.","triggerScenarios":"One thread calls start() while another calls close() on the same FfiRuntimeHost; close() sets disposed before start finishes its blocking native call.","commonSituations":"Application shutdown hook racing with initialization; a timeout-based watchdog closing the client while startup is still in flight; double-managed lifecycle (container + app both closing).","solutions":["Ensure close() is not invoked until after start() completes; serialize lifecycle with the same lock or a startup Future.","Check return value / exceptions of start() before calling close() in shutdown paths.","Orchestrate lifecycle in a single owner component.","Catch IllegalStateException and treat as benign during shutdown."],"exampleFix":"// before\nnew Thread(() -> client.close()).start();\nclient.start(entrypoint, options); // may race\n// after\nclient.start(entrypoint, options);\nRuntime.getRuntime().addShutdownHook(new Thread(client::close));","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { host.start(e, o); } catch (IllegalStateException ex) { if (shuttingDown.get()) { log.info(\"startup raced with shutdown, ignoring\"); return; } throw ex; }","preventionTips":["Serialize lifecycle: no close() until start() returns","Use a single owner thread/executor for init and shutdown","Add shutdown hooks instead of ad-hoc closing threads"],"tags":["java","ffi","concurrency","race-condition"],"backgroundTag":"invalid-state-transition","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"}