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

  1. Fix the failing Background step in the mock feature — run it as a normal feature test to see the full failure first
  2. Check result.getError().getMessage() embedded in the exception (and its cause) for the underlying step error
  3. Remove heavy logic from Background and move optional setup into Scenario outlines or callonce
  4. 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

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


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)