{"record":{"id":"d4ca5e059369b222","repo":"karatelabs/karate","slug":"shutdown-in-progress-failed","errorCode":null,"errorMessage":"shutdown in progress failed: {}","messagePattern":"shutdown in progress failed: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"karate-js/src/main/java/io/karatelabs/common/KarateLifecycle.java","lineNumber":296,"sourceCode":"                results = new ArrayList<>();\n            }\n        }\n        if (joinable != null) {\n            return join(joinable);\n        }\n        return drain();\n    }\n\n    private static List<StopResult> join(CompletableFuture<List<StopResult>> other) {\n        try {\n            return other.get();\n        } catch (InterruptedException e) {\n            Thread.currentThread().interrupt();\n            synchronized (LOCK) {\n                return List.copyOf(results);\n            }\n        } catch (ExecutionException e) {\n            logger.warn(\"shutdown in progress failed: {}\", e.getCause() == null ? e : e.getCause().getMessage());\n            synchronized (LOCK) {\n                return List.copyOf(results);\n            }\n        }\n    }\n\n    private static List<StopResult> drain() {\n        List<Stoppable> snapshot;\n        synchronized (REGISTERED) {\n            snapshot = new ArrayList<>(REGISTERED);\n            REGISTERED.clear();\n        }\n        Collections.reverse(snapshot);\n        if (!snapshot.isEmpty()) {\n            logger.debug(\"stopping {} registered component(s)\", snapshot.size());\n        }\n        SHUTDOWN_THREAD.set(true);\n        try {","sourceCodeStart":278,"sourceCodeEnd":314,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/common/KarateLifecycle.java#L278-L314","documentation":"During `shutdownAll`, a component's shutdown task completed exceptionally (`ExecutionException` from the Future). The lifecycle logs this warning with the cause message, keeps whatever results were collected, and continues shutting down remaining components instead of aborting.","triggerScenarios":"Any registered stoppable whose `stop()` throws during `shutdownAll()` — e.g. closing a socket already closed by a peer, a JDBC driver failing to close a broken connection, an HTTP client throwing on shutdown.","commonSituations":"Peer already closed the connection so stop() fails idempotently-badly; stop() called twice; resource in a broken state after a test failure; stop() performing I/O on a dead resource.","solutions":["Inspect the logged cause to find which component's stop() failed and why","Make the component's stop() idempotent and tolerant of already-closed resources","Check for double-shutdown paths (component stopping itself and lifecycle stopping it)","Fix the underlying resource state (e.g. don't attempt network close on a dead socket)"],"exampleFix":"// before\npublic void stop() { socket.close(); } // throws if already closed\n// after\npublic void stop() { if (socket != null && !socket.isClosed()) socket.close(); }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"public void stop() {\n    try { closeResources(); }\n    catch (Exception e) { log.debug(\"stop failed (already closed?)\", e); } // keep stop idempotent\n}","preventionTips":["Make every stoppable's stop() idempotent and exception-tolerant","Avoid double-stop paths (component self-stop + lifecycle stop)","Check closed-state flags before closing sockets/streams"],"tags":["lifecycle","shutdown","cleanup","concurrency"],"backgroundTag":"resource-cleanup-failed","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-16T19:17:19.609Z"}