karatelabs/karate · error · RuntimeException

karate.match(String) is not available in this context

Error message

karate.match(String) is not available in this context

What it means

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.

Solutions

  1. Move the karate.match(String) call inside a running Scenario (Background or Scenario block) so a current runtime exists.
  2. Use the two-argument form karate.match(actual, expected) when you have plain values — it does an equals comparison without needing a runtime.
  3. In mock contexts, resolve needed values into JS variables first and compare with the two-argument form or plain JS.
  4. If this runs during feature setup, ensure the runtime is initialized before the JS bridge is invoked.

Example fix

// before (mock handler, no scenario runtime)
var ok = karate.match("response == { id: '#number' }");
// after (two-arg form, no runtime needed)
var ok = karate.match(response, { id: '#number' });
Defensive patterns

Strategy: fallback

Validate before calling

// run inside a Scenario; if in a mock, use value-based comparison instead
var hasRuntime = typeof scenario !== 'undefined' || karate.match(response, response) !== undefined;

Type guard

function matchAvailable() { try { karate.match('1 == 1'); return true; } catch (e) { return !String(e.message).includes('not available in this context'); } }

Try / catch

var result;
try {
  result = karate.match('response == { id: \'#number\' }');
} catch (e) {
  if (String(e.message).includes('not available in this context')) {
    result = karate.match(response, { id: '#number' }); // two-arg fallback
  } else { throw e; }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12). Data as JSON: /api/errors/7b4fd69eb2c438e0. Report an issue: GitHub.

Appendix: source

Thrown at karate-core/src/main/java/io/karatelabs/core/KarateJs.java:677

                // Delegate to the same evaluator the `match` keyword uses so both operands
                // get identical handling — JsonPath ($-prefixed, wildcards), JSON literals,
                // embedded expressions, etc. Reusing StepExecutor.evalMatchString keeps the
                // JS API and the keyword from drifting (issue #2894).
                //
                // The string operands are resolved against the *currently executing*
                // scenario, not the scenario where this `karate` bridge was defined. A
                // condition closure built in feature A and passed to feature B (via
                // `call read('B.feature') filter`) must see B's variables when B invokes
                // it — the caller's `response` lives in B's scope, not A's. Using the
                // captured getRuntime() (A) surfaced a "ReferenceError: response is not
                // defined". Fall back to the captured runtime outside a live scenario
                // (e.g. mock context).
                ScenarioRuntime rt = ScenarioRuntime.currentOrNull();
                if (rt == null) {
                    rt = getRuntime();
                }
                if (rt == null) {
                    throw new RuntimeException("karate.match(String) is not available in this context");
                }
                String expression = args[0].toString();
                Result result = rt.getExecutor().evalMatchString(expression, null);
                return result.toMap();
            }
        };
    }

    private JavaInvokable call() {
        return args -> {
            ScenarioRuntime rt = getRuntime();
            if (rt == null) {
                throw new RuntimeException("karate.call() is not available in this context");
            }
            if (args.length == 0) {
                throw new RuntimeException("karate.call() requires at least one argument (feature path)");
            }
            // V1 compatible signatures:

View on GitHub (pinned to a22eb90246)