{"record":{"id":"6c59c1171852095f","repo":"karatelabs/karate","slug":"karate-call-requires-a-feature-context","errorCode":null,"errorMessage":"karate.call() requires a feature context","messagePattern":"karate\\.call\\(\\) requires a feature context","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"karate-core/src/main/java/io/karatelabs/core/ScenarioRuntime.java","lineNumber":579,"sourceCode":"            return new HashMap<>(result);\n        }\n    }\n\n    /**\n     * Execute a feature via karate.call() and return its result variables.\n     * This is used for JavaScript calls like: karate.call('other.feature', { arg: 'value' })\n     *\n     * Supports call-by-tag syntax:\n     * - call('file.feature@name=tagvalue') - call feature, run only scenario with matching tag\n     * - call('@tagname') - call scenario in same file by tag\n     *\n     * When arg is a List, loops over elements (same as `call read('path') array`) and\n     * returns a List of result maps.\n     */\n    @SuppressWarnings(\"unchecked\")\n    public Object executeJsCall(String path, Object arg) {\n        if (featureRuntime == null) {\n            throw new RuntimeException(\"karate.call() requires a feature context\");\n        }\n\n        // Parse path, tag selector and line filter — shared parser keeps JS\n        // (karate.call) and keyword (`call read(...)`) syntax in lockstep.\n        StepUtils.ParsedFeaturePath parsed = StepUtils.parseFeaturePath(path);\n        String tagSelector = parsed.tagSelector();\n        Set<Integer> lineFilters = parsed.lineFilters();\n        Feature calledFeature;\n        if (parsed.sameFile()) {\n            // call('@tagname') — scenario in the same file\n            calledFeature = featureRuntime.getFeature();\n        } else {\n            Resource calledResource = featureRuntime.resolve(parsed.path());\n            // A .js target is a callable helper, not a feature — evaluate and invoke it,\n            // mirroring read()/callSingle and the `call` keyword (and v1, which dispatched\n            // on the resolved type). Blindly parsing it as a feature silently returned an\n            // empty result, dropping the helper's functions.\n            if (\"js\".equals(calledResource.getExtension())) {","sourceCodeStart":561,"sourceCodeEnd":597,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/core/ScenarioRuntime.java#L561-L597","documentation":"executeJsCall implements karate.call() from JS, resolving a feature path (with optional tag selector and line filter) and invoking it against the current FeatureRuntime. A feature context is mandatory — the called feature runs as a child FeatureRuntime of the caller's. When featureRuntime is null, this RuntimeException is thrown.","triggerScenarios":"Calling karate.call('classpath:...') from JS that is not executing inside a feature — e.g. karate.callSingle() cached JS, karate-config.js evaluation, or a standalone script executed through the Karate JS engine outside a feature run.","commonSituations":"Wrapping feature calls in shared utility JS used by both callSingle and scenarios; calling features from karate-config.js during config init; using karate.call() in setup hooks that predate the feature runtime.","solutions":["Move the karate.call() usage into scenario or Background JS within a running feature.","In karate-config.js, replace karate.call() with configure/variable assignment or use it only for pure JS helpers.","If suite-level reuse is needed, call the feature at scenario level once and pass its results down instead of calling from callSingle JS.","Ensure the caller feature is launched through Runner.path(...) so a FeatureRuntime exists."],"exampleFix":"// before: inside karate.callSingle() JS\nvar result = karate.call('classpath:helpers/lookup.feature');\n\n// after: inside a scenario\n* def result = call read('classpath:helpers/lookup.feature')","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// prefer the keyword inside features; reserve karate.call() for scenario JS\n// * def result = call read('classpath:lookup.feature') { id: 1 }","tryCatchPattern":"try {\n    var result = karate.call('classpath:lookup.feature', { id: 1 });\n} catch (e) {\n    if (String(e).indexOf('requires a feature context') >= 0) {\n        karate.log('karate.call outside feature scope');\n        throw e; // structural misuse — do not swallow\n    }\n    throw e;\n}","preventionTips":["Never call features from karate-config.js or callSingle JS","Use the `call read(...)` keyword inside scenarios instead of karate.call()","Keep feature-calling helpers scenario-scoped","Run features through Runner so the FeatureRuntime exists"],"tags":["karate-call","karate-js","lifecycle"],"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"}