{"record":{"id":"c4b08e2ce589d8be","repo":"karatelabs/karate","slug":"cached-exception-message","errorCode":null,"errorMessage":"<cached exception message>","messagePattern":"<cached exception message>","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"karate-core/src/main/java/io/karatelabs/core/ScenarioRuntime.java","lineNumber":951,"sourceCode":"                    String found = findNonJsonValue(list.get(i), path + \"[\" + i + \"]\", visited);\n                    if (found != null) {\n                        return found;\n                    }\n                }\n                return null;\n            }\n            return path;\n        } finally {\n            visited.remove(value);\n        }\n    }\n\n    /**\n     * Unwrap cached result - throws if it's a cached exception.\n     */\n    private Object unwrapCachedResult(Object cached) {\n        if (cached instanceof CallSingleException) {\n            throw new RuntimeException(((CallSingleException) cached).cause.getMessage(),\n                    ((CallSingleException) cached).cause);\n        }\n        return StepUtils.deepCopy(cached);\n    }\n\n    /**\n     * Wrapper for cached exceptions to distinguish from null results.\n     */\n    private static class CallSingleException {\n        final Exception cause;\n        CallSingleException(Exception cause) {\n            this.cause = cause;\n        }\n    }\n\n    private void inheritVariables() {\n        boolean sharedScope = featureRuntime.isSharedScope();\n        // First check for callerScenario (the currently executing scenario that made the call)","sourceCodeStart":933,"sourceCodeEnd":969,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/core/ScenarioRuntime.java#L933-L969","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Fix the root cause shown in the chained `cause` (the original callSingle exception) and restart the JVM/test run to clear the cache","Check the callSingle expression for idempotency and error handling; wrap risky logic so it returns a value instead of throwing","Clear or key the cache differently (unique callSingle key per environment/inputs) so a poisoned entry is not reused"],"exampleFix":"// before: callSingle throws and poisons the cache\n* def config = karate.callSingle('lookup.feature')\n// after: make the callSingle resilient\n* def config = karate.callSingle('function(){ try { return karate.call('lookup.feature'); } catch (e) { return { error: e.message } } })()","handlingStrategy":"try-catch","validationCode":"// cannot inspect the cache directly; make the callSingle expression defensive\nfunction(){ try { return karate.call('lookup.feature'); } catch (e) { return { error: e.message }; } }","typeGuard":null,"tryCatchPattern":"try { result = karate.callSingle('lookup.feature'); } catch (RuntimeException e) { logger.error(\"cached callSingle failure\", e.getCause()); throw e; }","preventionTips":["Make callSingle expressions idempotent and never throw (return error objects instead)","Use unique callSingle keys per environment/inputs","After fixing the root cause, restart the test JVM to clear the in-memory cache"],"tags":["callsingle","cache","runtime"],"backgroundTag":"internal-invariant-violation","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}