karatelabs/karate · error · RuntimeException
mock background failed at line
Error message
mock background failed at line <line>: <message>
What it means
MockHandler.initRuntime executes the feature's Background section once at mock-server initialization and, if any Background step fails, wraps the step's failure in a RuntimeException. This fails fast at server startup because a broken Background would leave mock state incomplete for every request.
Solutions
- Fix the failing Background step in the mock feature — run it as a normal feature test to see the full failure first
- Check result.getError().getMessage() embedded in the exception (and its cause) for the underlying step error
- Remove heavy logic from Background and move optional setup into Scenario outlines or callonce
- Validate the feature standalone (Runner / karate runner) before wiring it into MockServer
Example fix
// before
Background:
* def user = call read('users.feature')
* match user.id == '#number'
// after (guard the step and fail with a clear message)
Background:
* def user = call read('users.feature')
* assert user != null : 'users.feature did not return a user' Defensive patterns
Strategy: validation
Validate before calling
StepResult r = new StepExecutor(runtime).execute(step);
if (r.isFailed()) throw new IllegalStateException("background step line " + step.getLine() + " failed: " + r.getError().getMessage()); Try / catch
try { server = MockServer.builder().feature(path).http(port).build().start(); } catch (RuntimeException e) { if (e.getMessage().startsWith("mock background failed")) { log.error("Mock feature Background invalid: {}", e.getCause(), e); } throw e; } Prevention
- Run the mock feature as a normal Karate feature in CI before using it as a mock
- Keep Background minimal — only variable setup, no brittle match assertions
- Read the wrapped cause (result.getError()) for the real step failure
When it happens
Trigger: Calling MockServer.start() with a feature whose Background steps fail — e.g. a failing match assertion, a JS error, or a missing variable defined via call in the Background.
Common situations: Refactoring a shared feature reused as a mock so its Background now depends on an undefined variable; a broken JSON/cucumber expression in a Background step; environment-specific config not available when the mock boots.
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
- at least one feature file is required
- karate-boot.js evaluation failed
- start() needs at least one argument: feature path or config…
- start() config requires 'mock' key with feature path
- start() argument must be a string path or config map
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/c775a968467b8a86.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/core/MockHandler.java:289
currentRequest != null ? markRequestDerived(runtime, currentRequest.getMultiParts()) : null);
engine.put("requestCookies", (JsLazy) () ->
currentRequest != null ? markRequestDerived(runtime, currentRequest.getCookies()) : null);
// Put args into globals if provided
if (args != null) {
globals.putAll(args);
for (var entry : args.entrySet()) {
engine.put(entry.getKey(), entry.getValue());
}
}
// Execute background once on initialization using StepExecutor
StepExecutor executor = new StepExecutor(runtime);
if (feature.isBackgroundPresent()) {
for (Step step : feature.getBackground().getSteps()) {
StepResult result = executor.execute(step);
if (result.isFailed()) {
throw new RuntimeException("mock background failed at line " + step.getLine() + ": " +
result.getError().getMessage(), result.getError());
}
}
// Save background variables to globals
saveGlobals(engine);
// Transfer configure settings to MockConfig
KarateConfig karateConfig = runtime.getConfig();
if (karateConfig.isCorsEnabled()) {
config.setCorsEnabled(true);
}
Object responseHeaders = karateConfig.getResponseHeaders();
if (responseHeaders instanceof Map) {
config.setResponseHeaders((Map<String, Object>) responseHeaders);
}
Object beforeScenario = karateConfig.getBeforeScenario();
if (beforeScenario instanceof JavaCallable callable) {
config.setBeforeScenario(callable);View on GitHub (pinned to a22eb90246)