karatelabs/karate · error · RuntimeException

call with tag selector requires a feature context

Error message

call with tag selector requires a feature context

What it means

A 'call' step using a tag selector (e.g. 'call read("@tagName")') resolves against the current feature; when the step executor has no enclosing FeatureRuntime/Feature in context, Karate throws this RuntimeException because tag-based same-file calls have nothing to search.

Solutions

  1. Ensure the call is executed within a loaded feature (a proper FeatureRuntime / runner context)
  2. Replace the '@tag' selector with an explicit path to the feature or Scenario: 'call read("path/to/feature.feature")'
  3. If calling code directly, construct a Feature for the current resource so getFeature() is non-null

Example fix

// before: tag selector with no feature context
call read('@setup-data')
// after: call the feature explicitly or ensure runner context
call read('classpath:helpers/setup.feature')
Defensive patterns

Strategy: try-catch

Validate before calling

// guard before tag-selector calls: need a feature context
if (callExpr.startsWith("@") && featureRuntime == null) {
    throw new IllegalStateException("@tag call requires a loaded feature context");
}

Try / catch

try { result = karate.call(expr, arg); } catch (RuntimeException e) { if (e.getMessage().contains("requires a feature context")) { throw new IllegalStateException("use explicit feature path instead of @tag selector"); } throw e; }

Prevention

When it happens

Trigger: Invoking evalCallExpression / executeCallWithResult with call.sameFile=true (a '@tag' selector) while fr is null or fr.getFeature() is null — e.g. calling a tag-scoped section from outside a loaded feature, or embedding the step executor in a non-feature harness.

Common situations: Programmatic/driver use of Karate's step engine without a FeatureRuntime; running a snippet harness that calls tag sections; tests invoking karate.call() with a '@tag' path before any feature is loaded.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at karate-core/src/main/java/io/karatelabs/core/StepExecutor.java:440

            } else if (evaluated instanceof FeatureCall || evaluated instanceof Feature) {
                executeFeatureCall(evaluated, parts.arg(), resultVar);
                return;
            }
        }

        // Standard feature call
        CallExpression call = parseCallExpression(callExpr);
        call.resultVar = resultVar;

        // Resolve the feature file relative to current feature
        FeatureRuntime fr = runtime.getFeatureRuntime();
        Feature calledFeature;

        if (call.sameFile) {
            // Same-file tag call - use current feature
            calledFeature = fr != null ? fr.getFeature() : null;
            if (calledFeature == null) {
                throw new RuntimeException("call with tag selector requires a feature context");
            }
        } else {
            Resource calledResource = fr != null
                    ? fr.resolve(call.path)
                    : Resource.path(call.path);
            calledFeature = Feature.read(calledResource);
        }

        // Check if it's an array loop call
        if (call.argList != null) {
            runtime.setVariable(resultVar, callFeatureLoop(calledFeature, call.argList, call.tagSelector, call.lineFilters));
            return;
        }

        // Single call
        Map<String, Object> resultVars = callFeatureSingle(calledFeature, call.arg, call.tagSelector, call.lineFilters);
        if (resultVars != null) {
            runtime.setVariable(resultVar, resultVars);

View on GitHub (pinned to a22eb90246)