{"record":{"id":"7b4fd69eb2c438e0","repo":"karatelabs/karate","slug":"karate-match-string-is-not-available-in-this-context","errorCode":null,"errorMessage":"karate.match(String) is not available in this context","messagePattern":"karate\\.match\\(String\\) is not available in this context","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"karate-core/src/main/java/io/karatelabs/core/KarateJs.java","lineNumber":677,"sourceCode":"                // Delegate to the same evaluator the `match` keyword uses so both operands\n                // get identical handling — JsonPath ($-prefixed, wildcards), JSON literals,\n                // embedded expressions, etc. Reusing StepExecutor.evalMatchString keeps the\n                // JS API and the keyword from drifting (issue #2894).\n                //\n                // The string operands are resolved against the *currently executing*\n                // scenario, not the scenario where this `karate` bridge was defined. A\n                // condition closure built in feature A and passed to feature B (via\n                // `call read('B.feature') filter`) must see B's variables when B invokes\n                // it — the caller's `response` lives in B's scope, not A's. Using the\n                // captured getRuntime() (A) surfaced a \"ReferenceError: response is not\n                // defined\". Fall back to the captured runtime outside a live scenario\n                // (e.g. mock context).\n                ScenarioRuntime rt = ScenarioRuntime.currentOrNull();\n                if (rt == null) {\n                    rt = getRuntime();\n                }\n                if (rt == null) {\n                    throw new RuntimeException(\"karate.match(String) is not available in this context\");\n                }\n                String expression = args[0].toString();\n                Result result = rt.getExecutor().evalMatchString(expression, null);\n                return result.toMap();\n            }\n        };\n    }\n\n    private JavaInvokable call() {\n        return args -> {\n            ScenarioRuntime rt = getRuntime();\n            if (rt == null) {\n                throw new RuntimeException(\"karate.call() is not available in this context\");\n            }\n            if (args.length == 0) {\n                throw new RuntimeException(\"karate.call() requires at least one argument (feature path)\");\n            }\n            // V1 compatible signatures:","sourceCodeStart":659,"sourceCodeEnd":695,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/core/KarateJs.java#L659-L695","documentation":"The single-argument string form karate.match(\"expr\") needs a ScenarioRuntime to evaluate the expression (it delegates to the same evaluator as the `match` keyword, resolving variables against the currently executing scenario). The code first tries ScenarioRuntime.currentOrNull(), then the captured getRuntime(); if both are null there is no runtime/variable scope, so KarateJs throws. This typically happens when the karate bridge is used outside a live scenario, such as a standalone mock or utility context.","triggerScenarios":"Calling karate.match('someVar == expected') (one string argument) when no ScenarioRuntime is active and the bridge holds no runtime — e.g. inside a mock-server handler, a karate-config hook without a scenario, or JS evaluated via an engine not attached to a scenario.","commonSituations":"Mock context: condition closures or JS helpers invoked from a mock server where no scenario is executing. Also setup/teardown hooks or standalone JS evaluation where the caller assumed scenario variables were available.","solutions":["Move the karate.match(String) call inside a running Scenario (Background or Scenario block) so a current runtime exists.","Use the two-argument form karate.match(actual, expected) when you have plain values — it does an equals comparison without needing a runtime.","In mock contexts, resolve needed values into JS variables first and compare with the two-argument form or plain JS.","If this runs during feature setup, ensure the runtime is initialized before the JS bridge is invoked."],"exampleFix":"// before (mock handler, no scenario runtime)\nvar ok = karate.match(\"response == { id: '#number' }\");\n// after (two-arg form, no runtime needed)\nvar ok = karate.match(response, { id: '#number' });","handlingStrategy":"fallback","validationCode":"// run inside a Scenario; if in a mock, use value-based comparison instead\nvar hasRuntime = typeof scenario !== 'undefined' || karate.match(response, response) !== undefined;","typeGuard":"function matchAvailable() { try { karate.match('1 == 1'); return true; } catch (e) { return !String(e.message).includes('not available in this context'); } }","tryCatchPattern":"var result;\ntry {\n  result = karate.match('response == { id: \\'#number\\' }');\n} catch (e) {\n  if (String(e.message).includes('not available in this context')) {\n    result = karate.match(response, { id: '#number' }); // two-arg fallback\n  } else { throw e; }\n}","preventionTips":["Use karate.match(String) only inside running Scenarios or Background blocks.","In mock handlers, prefer the two-argument karate.match(actual, expected) form which needs no runtime.","Resolve all needed variables into JS values before calling match so the expression string does not depend on scenario scope."],"tags":["javascript","runtime-context","mock","unsupported-operation"],"backgroundTag":"unsupported-operation","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"}