karatelabs/karate · error · RuntimeException

same-file tag call requires a feature context

Error message

same-file tag call requires a feature context

What it means

Identical in intent to the previous error but raised on the FeatureCall code path: when a `call` argument is a FeatureCall marked same-file with a tag selector, the executor derives the feature from the current feature runtime; if none exists (fr is null or has no Feature) it throws. A same-file tag call fundamentally requires a live feature to filter scenarios from.

Solutions

  1. Execute the call within a feature runtime that has an active Feature
  2. Replace the same-file tag call with an explicit path call: call classpath:path/to/file.feature@tag
  3. Avoid caching/reusing FeatureCall objects across contexts
  4. Verify the feature runtime (fr) is set before dynamic calls

Example fix

// before
* def fc = karate.readAndCall('@smoke')  // same-file, no feature ctx
// after
* call classpath:examples/users.feature@smoke
Defensive patterns

Strategy: validation

Try / catch

try { karate.call(fc) } catch (e) { if (String(e).indexOf('feature context') >= 0) karate.call('explicit.feature@tag') }

Prevention

When it happens

Trigger: A call step whose argument evaluates to a same-file FeatureCall (created with a tag selector) executed in a context with no current Feature; e.g. dynamic `call foo` where foo was built programmatically as a same-file call and run outside a feature.

Common situations: Constructing FeatureCall objects in JS/Java and invoking them from embedded scripts; runner setups that execute steps without an owning feature; refactors that moved a same-file tag call into a shared utility executed standalone.

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/cb529f13b660f895. Report an issue: GitHub.

Appendix: source

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

    /**
     * Execute a feature call with a Feature or FeatureCall object.
     * Used when the call expression evaluates to a Feature variable.
     * Supports array loop calling when argExpr evaluates to a List.
     */
    @SuppressWarnings("unchecked")
    private void executeFeatureCall(Object featureObj, String argExpr, String resultVar) {
        FeatureRuntime fr = runtime.getFeatureRuntime();

        Feature calledFeature;
        String tagSelector = null;

        if (featureObj instanceof FeatureCall) {
            FeatureCall fc = (FeatureCall) featureObj;
            if (fc.isSameFile()) {
                calledFeature = fr != null ? fr.getFeature() : null;
                if (calledFeature == null) {
                    throw new RuntimeException("same-file tag call requires a feature context");
                }
            } else {
                calledFeature = fc.getFeature();
            }
            tagSelector = fc.getTagSelector();
        } else if (featureObj instanceof Feature) {
            calledFeature = (Feature) featureObj;
        } else {
            throw new RuntimeException("expected Feature or FeatureCall, got: " + featureObj.getClass());
        }

        // Karate-expression eval handles inline JSON with embedded `#(...)`,
        // arrays, variables, and bare JS uniformly.
        Object argObj = argExpr == null ? null : evalKarateExpression(argExpr);

        // Check if it's an array loop call
        if (argObj instanceof List) {
            List<Map<String, Object>> results = callFeatureLoop(calledFeature, (List<?>) argObj, tagSelector, null);

View on GitHub (pinned to a22eb90246)