{"record":{"id":"fff5931c997e2ca1","repo":"karatelabs/karate","slug":"channel-can-only-be-called-within-a-scenario","errorCode":null,"errorMessage":"channel() can only be called within a scenario","messagePattern":"channel\\(\\) can only be called within a scenario","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"karate-core/src/main/java/io/karatelabs/core/KarateJs.java","lineNumber":1203,"sourceCode":"    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.\n            FeatureRuntime fr = rt.getFeatureRuntime();\n            Suite suite = fr != null ? fr.getSuite() : null;\n            ChannelFactory factory = suite != null ? suite.getChannelFactory(type) : null;\n            try {\n                if (factory == null) {\n                    // No ext registered a factory for this type — resolve by name convention,\n                    // mirroring boot.ext: channel('grpc') -> io.karatelabs.ext.grpc.GrpcChannelFactory.\n                    String cap = Character.toUpperCase(type.charAt(0)) + type.substring(1);\n                    String factoryClass = \"io.karatelabs.ext.\" + type + \".\" + cap + \"ChannelFactory\";\n                    Class<?> clazz = Class.forName(factoryClass);\n                    factory = (ChannelFactory) clazz.getDeclaredConstructor().newInstance();\n                }\n                // Channels self-configure via their rich JS object, not via global config.\n                Channel channel = factory.create(rt, new HashMap<>());\n                rt.registerChannel(channel);","sourceCodeStart":1185,"sourceCodeEnd":1221,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/core/KarateJs.java#L1185-L1221","documentation":"Channels are scenario-scoped: karate.channel(type) resolves the ChannelFactory via the current ScenarioRuntime's Suite. When no runtime is active (boot scripts, afterSuite, pure JS eval outside a scenario) the call cannot proceed and throws this error.","triggerScenarios":"Calling karate.channel('kafka') in karate-config.js, a call-single JS file executed outside a scenario, @AfterSuite hook, or any JS context where getRuntime() returns null.","commonSituations":"Utility scripts shared between scenario and boot contexts; setting up a channel listener in a suite hook instead of a scenario; calling channel() from a JVM-embedded Karate engine without running a feature scenario.","solutions":["Call karate.channel() only inside a running scenario step or scenario-scoped JS","Move channel setup into the scenario (or Background) rather than suite/boot hooks","If using the embedded engine, ensure a scenario runtime exists before resolving channels."],"exampleFix":"// before (afterSuite JS)\nkarate.channel('kafka').close();\n// after — close inside the scenario\nScenario: teardown\n* def ch = karate.channel('kafka')\n* ch.close()","handlingStrategy":"try-catch","validationCode":"// JS: only call channel() inside scenario scope; guard shared helpers\nfunction channelInScenario(type) { try { return karate.channel(type); } catch (e) { return null; } }","typeGuard":null,"tryCatchPattern":"try { var ch = karate.channel('kafka'); } catch (e) { if (String(e).indexOf('within a scenario') >= 0) karate.warn('move channel() into a scenario'); throw e; }","preventionTips":["Use karate.channel() only in scenario steps/scenario-scoped JS","Do channel setup/teardown in scenarios, not suite or boot hooks","For embedded engine use, ensure a scenario runtime exists first"],"tags":["javascript","lifecycle","channels"],"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"}