karatelabs/karate · error · RuntimeException
karate.setup() requires a feature context
Error message
karate.setup() requires a feature context
What it means
executeSetup runs the @setup-tagged scenario of the current feature (karate.setup()). It requires a FeatureRuntime context — the enclosing feature being executed by the Karate runner. When ScenarioCaller/JS code calls karate.setup() outside a feature execution (featureRuntime is null), this RuntimeException is thrown.
Solutions
- Call karate.setup() only from within a running feature's scenario or JS executed there.
- If the code is shared via karate.callSingle(), refactor to not use setup (return data directly from the JS function).
- If you control the caller, ensure featureRuntime is attached by running through a feature (Runner.path(...)) rather than ad-hoc JS evaluation.
- Check for accidental API confusion: karate.call() / karate.setupOnce() have similar context requirements — verify you meant setup().
Example fix
// before: karate-config.js or callSingle JS
var data = karate.setup('makeData');
// after: call setup inside a scenario / feature-scoped JS
Scenario:
* def data = karate.setup('makeData') Defensive patterns
Strategy: type-guard
Type guard
function canSetup() {
// setup needs a feature context; only call it from scenario-scoped JS
return typeof karate.setup === 'function' && karate.runtime != null;
}
// usage inside a scenario:
// if (canSetup()) karate.setup('makeData'); Try / catch
try {
var data = karate.setup('makeData');
} catch (e) {
if (String(e).indexOf('requires a feature context') >= 0) {
karate.log('setup called outside feature scope; using defaults');
data = defaultData;
} else { throw e; }
} Prevention
- Never call karate.setup() from karate-config.js or callSingle JS
- Use setup only in scenario/Background scope of a running feature
- Launch features via Runner.path(...) so FeatureRuntime exists
- Do not move scenario-scoped JS helpers into suite-level utilities without auditing karate.* usage
When it happens
Trigger: Calling karate.setup() (optionally with a name) from JS code that is not running inside a feature's scenario — e.g. from callSingle() cached code, a standalone JS script, or a config script evaluated before the feature runtime is attached.
Common situations: Using karate.setup() inside karate.callSingle() cached JS, which runs at suite level with no feature context; invoking setup helpers from karate-config.js; refactored JS moved from a Scenario into shared JS executed out of context.
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
- karate.setup() is not available in this context
- karate.setupOnce() requires a feature context
- karate.driver can only be read within a scenario
- karate.call() requires a feature context
- karate.callonce() requires a feature context
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/1715ddc2009ab5bb.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/core/ScenarioRuntime.java:513
}
logger.debug("Evaluated {}: {} variables", displayName, vars.size());
return vars;
} else if (result != null) {
logger.warn("{} did not return an object, got: {}", displayName, result.getClass().getSimpleName());
}
return null;
} catch (Exception e) {
logger.warn("Failed to evaluate {}: {}", displayName, e.getMessage());
throw new RuntimeException("Config evaluation failed: " + displayName + " - " + e.getMessage(), e);
}
}
/**
* Execute the @setup scenario and return all its variables.
*/
public Map<String, Object> executeSetup(String name) {
if (featureRuntime == null) {
throw new RuntimeException("karate.setup() requires a feature context");
}
Scenario setupScenario = scenario.getFeature().getSetup(name);
if (setupScenario == null) {
String message = "no scenario found with @setup tag";
if (name != null) {
message = message + " and name '" + name + "'";
}
throw new RuntimeException(message);
}
// Run the setup scenario without background
ScenarioRuntime sr = new ScenarioRuntime(featureRuntime, setupScenario);
sr.setSkipBackground(true);
sr.call();
// The setup runtime re-evaluates config, and a failure there is now captured rather than
// thrown from the constructor. call()'s failed result is discarded here, so without this the
// caller gets an empty variable map and the config error resurfaces as a baffling
// "x is not defined" wherever a setup variable was expected. Fail where the cause is.
Throwable setupConfigError = sr.getConfigError();View on GitHub (pinned to a22eb90246)