{"record":{"id":"d47204655ea25bb9","repo":"karatelabs/karate","slug":"karate-driver-can-only-be-read-within-a-scenario","errorCode":null,"errorMessage":"karate.driver can only be read within a scenario","messagePattern":"karate\\.driver can only be read within a scenario","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"karate-core/src/main/java/io/karatelabs/core/KarateJs.java","lineNumber":1188,"sourceCode":"            } catch (Exception e) {\n                throw new RuntimeException(\"Failed to write file: \" + file.getAbsolutePath(), e);\n            }\n        };\n    }\n\n    /**\n     * JS-side access to the active browser driver, initialising it lazily from\n     * {@code configure driver = { ... }} on first read — the JS equivalent of the\n     * {@code * driver ...} step. Useful when driver lifecycle is orchestrated inside\n     * a JS function (e.g. iterating over a list of browser configs in a grid run),\n     * where Gherkin steps aren't reachable per iteration. Returns the same instance\n     * exposed via the {@code driver} root binding; after {@code driver.quit()} a\n     * subsequent read re-inits cleanly via {@link ScenarioRuntime#getDriver()}.\n     */\n    private io.karatelabs.driver.Driver getDriverLazy() {\n        ScenarioRuntime rt = getRuntime();\n        if (rt == null) {\n            throw new RuntimeException(\"karate.driver can only be read within a scenario\");\n        }\n        return rt.getDriver();\n    }\n\n    // ========== Channel Support ==========\n\n    private JavaInvokable channel() {\n        return args -> {\n            if (args.length == 0) {\n                throw new RuntimeException(\"channel() needs a type argument, e.g. karate.channel('kafka')\");\n            }\n            String type = args[0].toString();\n            ScenarioRuntime rt = getRuntime();\n            if (rt == null) {\n                throw new RuntimeException(\"channel() can only be called within a scenario\");\n            }\n            // An ext (e.g. boot.ext('grpc')) may have registered a factory on the Suite at boot;\n            // it wins over the name-convention fallback. See Suite#registerChannelFactory.","sourceCodeStart":1170,"sourceCodeEnd":1206,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/core/KarateJs.java#L1170-L1206","documentation":"The karate.driver root binding lazily initializes the active browser driver by asking the current ScenarioRuntime. Outside a scenario (e.g. in a boot script, JS function eval before/after a feature, or a standalone JS context) there is no runtime, so reading karate.driver throws instead of returning a useless null.","triggerScenarios":"Reading `karate.driver` in karate-config.js / boot-time JS, in a called JS-only context with no scenario, or after the scenario runtime has been torn down (e.g. in an afterSuite hook).","commonSituations":"Shared utility JS scripts that reference karate.driver unconditionally but are also loaded at boot; calling driver operations in background/setup hooks without an active scenario; assuming the driver survives after quit/teardown.","solutions":["Only access karate.driver inside a running scenario (Scenario/Background/JS within a scenario)","Move driver-dependent logic from boot/config scripts into scenario steps","In shared JS, guard with karate.runtime info or pass the driver in as a parameter instead of reading the global binding."],"exampleFix":"// before (karate-config.js)\nconfig.driver = karate.driver; // throws at boot\n// after\nconfig.getDriver = function() { return karate.driver; }; // read lazily inside a scenario","handlingStrategy":"type-guard","validationCode":"// JS: only inside a scenario; in shared scripts defer the read\nvar getDriver = function() { return karate.driver; };","typeGuard":"// JS: cannot query runtime presence directly; wrap reads in functions instead of eager access\nfunction safeDriver() { try { return karate.driver; } catch (e) { return null; } }","tryCatchPattern":"try { var d = karate.driver; } catch (e) { karate.warn('driver unavailable outside scenario'); }","preventionTips":["Never read karate.driver in karate-config.js or boot scripts","Access driver only inside Scenario/Background scope","Re-read karate.driver after driver.quit() to re-init lazily","Parameterize shared utility scripts instead of reading global bindings"],"tags":["javascript","lifecycle","driver","karate-js"],"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"}