karatelabs/karate · error · RuntimeException
expected Feature or FeatureCall, got:
Error message
expected Feature or FeatureCall, got:
What it means
The call step executor expects its evaluated feature argument to be either a Feature object or a FeatureCall; anything else means the argument was not resolvable to a callable feature. The error includes the actual Java class found, making it a type-validation failure for the `call`/`callonce` keyword's argument.
Solutions
- Ensure the called variable is a feature path string passed through read(): `call read('other.feature')`
- print the variable to see its actual type before the call
- If you want call results, use `def res = call ...` and access res.response, do not call the result again
- Assign the feature explicitly: def f = read('other.feature') then call f
Example fix
// before
* def data = { a: 1 }
* call data
// after
* call read('other.feature') Defensive patterns
Strategy: type-guard
Validate before calling
// karate
* if (!(typeof featureRef == 'string') && !featureRef.read) karate.fail('not a feature ref') Type guard
function isFeatureRef(v) { return typeof v === 'string' || (v && typeof v === 'object' && !!v.read); } Prevention
- Call features via call read('path.feature') to guarantee the right shape
- Do not re-call results of previous calls
- Keep feature-path variables separate from data variables by naming convention (e.g. featX)
When it happens
Trigger: `call <expr>` where expr evaluates to a Map, String, List, or other object that is neither Feature nor FeatureCall — e.g. calling a JSON variable, or a variable set to the result of a previous call (call result object) rather than a feature reference.
Common situations: Mistyping a variable name so `call foo` picks up a data table or response payload instead of the feature; calling the result of another call (`* def r = call x ... * call r`) which is a result wrapper, not a FeatureCall; version migration where call results changed shape.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- call with tag selector requires a feature context
- called feature failed
- same-file tag call requires a feature context
- call expression must resolve to a feature path:
- boot.ext(' '): does not implement io.karatelabs.core.Ext
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/69e70615893940e6.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/core/StepExecutor.java:2771
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);
if (resultVar != null) {
runtime.setVariable(resultVar, results);
}
return;
}
// Single call with Map argument
Map<String, Object> callArg = null;
if (argObj instanceof Map) {View on GitHub (pinned to a22eb90246)