karatelabs/karate · error · RuntimeException

<cached exception message>

Error message

<cached exception message>

What it means

Karate caches the result of a `call single` expression. If the cached result is actually a CallSingleException (the call failed previously), unwrapCachedResult rethrows it as a RuntimeException wrapping the original cause, so every consumer of the cache sees the same failure instead of a result.

Solutions

  1. Fix the root cause shown in the chained `cause` (the original callSingle exception) and restart the JVM/test run to clear the cache
  2. Check the callSingle expression for idempotency and error handling; wrap risky logic so it returns a value instead of throwing
  3. Clear or key the cache differently (unique callSingle key per environment/inputs) so a poisoned entry is not reused

Example fix

// before: callSingle throws and poisons the cache
* def config = karate.callSingle('lookup.feature')
// after: make the callSingle resilient
* def config = karate.callSingle('function(){ try { return karate.call('lookup.feature'); } catch (e) { return { error: e.message } } })()
Defensive patterns

Strategy: try-catch

Validate before calling

// cannot inspect the cache directly; make the callSingle expression defensive
function(){ try { return karate.call('lookup.feature'); } catch (e) { return { error: e.message }; } }

Try / catch

try { result = karate.callSingle('lookup.feature'); } catch (RuntimeException e) { logger.error("cached callSingle failure", e.getCause()); throw e; }

Prevention

When it happens

Trigger: Re-using a cached `call single` result when the original call had thrown: callSingle key maps to a CallSingleException and a subsequent callSingle with the same key reaches unwrapCachedResult.

Common situations: A `call single` block failed once (network blip, bad script) and remains in the in-memory cache; subsequent scenarios or retries re-throw the same cached error; users confused why the error persists after the underlying cause was fixed within the same JVM run.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12). Data as JSON: /api/errors/c4b08e2ce589d8be. Report an issue: GitHub.

Appendix: source

Thrown at karate-core/src/main/java/io/karatelabs/core/ScenarioRuntime.java:951

                    String found = findNonJsonValue(list.get(i), path + "[" + i + "]", visited);
                    if (found != null) {
                        return found;
                    }
                }
                return null;
            }
            return path;
        } finally {
            visited.remove(value);
        }
    }

    /**
     * Unwrap cached result - throws if it's a cached exception.
     */
    private Object unwrapCachedResult(Object cached) {
        if (cached instanceof CallSingleException) {
            throw new RuntimeException(((CallSingleException) cached).cause.getMessage(),
                    ((CallSingleException) cached).cause);
        }
        return StepUtils.deepCopy(cached);
    }

    /**
     * Wrapper for cached exceptions to distinguish from null results.
     */
    private static class CallSingleException {
        final Exception cause;
        CallSingleException(Exception cause) {
            this.cause = cause;
        }
    }

    private void inheritVariables() {
        boolean sharedScope = featureRuntime.isSharedScope();
        // First check for callerScenario (the currently executing scenario that made the call)

View on GitHub (pinned to a22eb90246)