{"record":{"id":"e1ff24ca3aaeb3ec","repo":"karatelabs/karate","slug":"provider-has-been-shut-down","errorCode":null,"errorMessage":"Provider has been shut down","messagePattern":"Provider has been shut down","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"karate-core/src/main/java/io/karatelabs/driver/PooledDriverProvider.java","lineNumber":102,"sourceCode":"\n    /**\n     * Create a pooled driver provider with explicit pool size.\n     * Use this when you need to override the auto-detected size.\n     *\n     * @param poolSize maximum number of drivers to create\n     */\n    public PooledDriverProvider(int poolSize) {\n        if (poolSize < 1) {\n            throw new IllegalArgumentException(\"Pool size must be at least 1\");\n        }\n        this.poolSize = poolSize;\n        this.availableDrivers = new ArrayBlockingQueue<>(poolSize);\n    }\n\n    @Override\n    public Driver acquire(ScenarioRuntime runtime, Map<String, Object> config) {\n        if (shutdown) {\n            throw new IllegalStateException(\"Provider has been shut down\");\n        }\n\n        // Initialize pool lazily with auto-detected size\n        ensurePoolInitialized(runtime);\n\n        // Check if this scenario already has a driver assigned (shouldn't happen normally)\n        Driver existing = assignedDrivers.get(runtime);\n        if (existing != null && !existing.isTerminated()) {\n            logger.debug(\"Returning existing driver for scenario: {}\", runtime.getScenario().getName());\n            return existing;\n        }\n\n        // Try to get a driver from the pool\n        Driver driver = takeHealthyFromPool(runtime.getScenario().getName());\n\n        if (driver == null) {\n            // Need to create a new driver or wait for one\n            synchronized (initLock) {","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/driver/PooledDriverProvider.java#L84-L120","documentation":"PooledDriverProvider refuses to hand out drivers once the provider has been shut down. After shutdown() is called the pool is permanently closed; any later acquire() call throws this IllegalStateException instead of silently creating or reusing a driver. It guards against using a torn-down pool in a new lifecycle phase.","triggerScenarios":"Calling Driver acquire(ScenarioRuntime, Map) after PooledDriverProvider.shutdown() has run — typically re-using a karate configuration/provider object across two suites, or calling acquire manually after the runner closed the pool.","commonSituations":"Reusing a single karate Configuration or custom provider across parallel runners where one finishes and shuts down the shared pool; embedding Karate in a long-lived application that shuts down the pool then attempts another scenario; test frameworks re-invoking karate.output methods after teardown.","solutions":["Create a new PooledDriverProvider for each suite/run instead of reusing a shut-down one","Ensure shutdown() is only called once, in a final afterSuite hook, and not in afterScenario/afterFeature hooks","Do not share a single provider instance across parallel runner threads; give each parallel branch its own pool","If embedding Karate, re-initialize the provider (or restart the Runner) after any shutdown"],"exampleFix":"// before\nPooledDriverProvider provider = new PooledDriverProvider();\nrunSuite(provider);\nprovider.shutdown();\nrunSecondSuite(provider); // IllegalStateException\n// after\nPooledDriverProvider provider = new PooledDriverProvider();\nrunSuite(provider);\nprovider.shutdown();\nPooledDriverProvider provider2 = new PooledDriverProvider(); // fresh pool\nrunSecondSuite(provider2);","handlingStrategy":"validation","validationCode":"// before acquiring\nif (provider.isShutdown()) { // expose or track shutdown state yourself\n    provider = new PooledDriverProvider();\n}\nDriver driver = provider.acquire(runtime, config);","typeGuard":"boolean poolUsable(PooledDriverProvider p) { return p != null && !p.isShutdown(); }","tryCatchPattern":"try { Driver d = provider.acquire(runtime, config); }\ncatch (IllegalStateException e) {\n    if (e.getMessage().contains(\"shut down\")) { provider = new PooledDriverProvider(); provider.acquire(runtime, config); }\n    else throw e;\n}","preventionTips":["Call shutdown() only once, in a final afterSuite/daemon-stop hook","Never share one provider across independent runs or parallel branches","Encapsulate provider lifecycle in a manager that recreates it after shutdown","Log shutdown events to trace who closed the pool"],"tags":["driver-pool","lifecycle","illegal-state"],"backgroundTag":"invalid-state-transition","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"}