{"record":{"id":"7c8bd0282c5647d9","repo":"karatelabs/karate","slug":"timed-out-stopping-after-ms","errorCode":null,"errorMessage":"timed out stopping {} after {}ms","messagePattern":"timed out stopping (.+?) after (.+?)ms","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"karate-js/src/main/java/io/karatelabs/common/KarateLifecycle.java","lineNumber":376,"sourceCode":"            return new StopResult(name, kind, Outcome.TIMED_OUT, Duration.ZERO);\n        }\n        logger.debug(\"stopping {} [{}]\", name, kind);\n        Future<?> future = pool().submit(() -> {\n            SHUTDOWN_THREAD.set(true);\n            try {\n                stoppable.stop();\n            } finally {\n                SHUTDOWN_THREAD.remove();\n            }\n        });\n        Outcome outcome;\n        try {\n            future.get(budgetNanos, TimeUnit.NANOSECONDS);\n            outcome = Outcome.STOPPED;\n        } catch (TimeoutException e) {\n            future.cancel(true);\n            outcome = Outcome.TIMED_OUT;\n            logger.warn(\"timed out stopping {} after {}ms\", name, TimeUnit.NANOSECONDS.toMillis(budgetNanos));\n        } catch (ExecutionException e) {\n            Throwable cause = e.getCause() == null ? e : e.getCause();\n            outcome = Outcome.FAILED;\n            logger.warn(\"failed to stop {}: {}\", name, cause.getMessage());\n        } catch (InterruptedException e) {\n            Thread.currentThread().interrupt();\n            future.cancel(true);\n            outcome = Outcome.TIMED_OUT;\n            logger.warn(\"interrupted while stopping {}\", name);\n        }\n        return new StopResult(name, kind, outcome, Duration.ofNanos(System.nanoTime() - start));\n    }\n\n    private static ExecutorService pool() {\n        synchronized (LOCK) {\n            if (stopPool == null) {\n                // cached, so a worker stuck on a stop() that ignores interrupts never blocks the next\n                stopPool = Executors.newCachedThreadPool(ThreadUtils.daemonFactory(\"karate-lifecycle-\"));","sourceCodeStart":358,"sourceCodeEnd":394,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/common/KarateLifecycle.java#L358-L394","documentation":"stopBounded() submits the Stoppable's stop logic to a thread pool and waits future.get(budgetNanos). When the stoppable does not finish within the budget, a TimeoutException is caught, the future is cancelled (interrupting the stop thread), and this warning is logged with Outcome.TIMED_OUT. The resource may still be in the process of shutting down or may be left partially stopped.","triggerScenarios":"Any Stoppable whose stop() implementation takes longer than the remaining shutdown budget: a stuck HTTP server waiting on open connections, a mock with long in-flight requests, a background process ignoring interrupts, or a stop() that blocks on I/O or locks.","commonSituations":"Embedded servers holding keep-alive connections; CI pipelines with tight shutdown timeouts; background JVM processes that don't respond to Thread.interrupt(); resources registered but never given a chance to drain.","solutions":["Increase the shutdown budget/timeout so the stoppable can finish gracefully","Find the resource named in the warning and fix its stop() path (close connections, drain queues) so it stops quickly","Reduce open work (in-flight requests, long polling) before shutdown begins","If the resource is known-safe to abandon, suppress or ignore the warning and ensure the JVM exits (e.g. System.exit or daemon threads)"],"exampleFix":"// before\nKarateLifecycle.budgetMillis = 500; // server.stop() takes ~2s\n// after\nKarateLifecycle.budgetMillis = 5000; // allow graceful stop","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { lifecycle.stop(); } catch (Exception e) { logger.warn('shutdown incomplete: {}', e.getMessage()); /* force cleanup */ }\n","preventionTips":["Size the shutdown budget to the slowest stoppable","Fix stop() implementations to honor interrupts","Close connections/queues before shutdown","Take thread dumps when timeouts recur"],"tags":["lifecycle","shutdown","timeout","thread"],"backgroundTag":"shutdown-timeout","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"}