{"record":{"id":"148c0cbcdf014759","repo":"karatelabs/karate","slug":"cache-second-argument-must-be-a-function","errorCode":null,"errorMessage":"cache() second argument must be a function: ","messagePattern":"cache\\(\\) second argument must be a function: ","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"karate-core/src/main/java/io/karatelabs/http/HttpRequest.java","lineNumber":762,"sourceCode":"     * on this request, and returns the same value on subsequent calls. The\n     * store dies with the request — never crosses request boundaries.\n     * <p>\n     * The two-argument form is the only supported shape. If the key is\n     * missing, the second argument must be a function (otherwise a runtime\n     * error is raised). A cached {@code null} or {@code undefined} return\n     * value is still a cache hit and does not re-invoke the function.\n     */\n    private JavaCallable cache() {\n        return (context, args) -> {\n            if (args.length < 2) {\n                throw new RuntimeException(\"cache() requires (key, fn)\");\n            }\n            String key = args[0] + \"\";\n            if (cacheStore != null && cacheStore.containsKey(key)) {\n                return cacheStore.get(key);\n            }\n            if (!(args[1] instanceof JavaCallable fn)) {\n                throw new RuntimeException(\"cache() second argument must be a function: \" + key);\n            }\n            Object value = fn.call(context);\n            if (cacheStore == null) {\n                cacheStore = new HashMap<>();\n            }\n            cacheStore.put(key, value);\n            return value;\n        };\n    }\n\n    @Override\n    public Object jsGet(String key) {\n        switch (key) {\n            case \"method\":\n                return method;\n            case \"body\":\n                return getBodyConverted();\n            case \"bodyString\":","sourceCodeStart":744,"sourceCodeEnd":780,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/http/HttpRequest.java#L744-L780","documentation":"The second argument to HttpRequest.cache(key, fn) must be a JavaCallable (a function/l callable). If the value passed is not invokable (string, number, map, null), the library throws this error appended with the cache key to identify the offending call site.","triggerScenarios":"Calling cache('key', someValue) where someValue is a pre-computed value or a variable that is null/undefined instead of a lambda; passing a Java object that is not a JavaCallable; typos like cache('k', fnName) where fnName is undefined and coerced to a non-callable.","commonSituations":"Users confusing cache() semantics — expecting it to store an existing value directly — when it is a lazy get-or-compute API; dynamic scripts where a function reference was shadowed by data; cross-language bindings (JS vs Java) where lambdas do not convert to JavaCallable.","solutions":["Wrap the value in a function: request.cache('key', () => value)","If you already have the value and just want to seed the cache, invoke it lazily anyway or write to the cache store directly","Check that the referenced function name exists and is not shadowed by a variable holding data","If calling from Java, pass a lambda/JavaCallable, not a raw Object"],"exampleFix":"// before\nrequest.cache(\"token\", token); // token is a string, throws\n// after\nrequest.cache(\"token\", () => token);","handlingStrategy":"type-guard","validationCode":"if (typeof fn !== 'function') throw new Error('cache() second argument must be a function for key: ' + key);\nrequest.cache(key, fn);","typeGuard":"function isCallable(v) { return v != null && (typeof v === 'function' || v instanceof Java.type('io.karatelabs.common.JavaCallable')); }","tryCatchPattern":"try {\n  request.cache(key, maybeFn);\n} catch (RuntimeException e) {\n  if (e.getMessage().startsWith(\"cache() second argument must be a function\")) {\n    request.cache(key, function() { return maybeFn; }); // wrap the value lazily\n  } else { throw e; }\n}","preventionTips":["Ensure the second argument is a lambda/function, not a value","Check that function names are not shadowed by data variables","In Java, pass a lambda (JavaCallable-compatible), never a raw Object"],"tags":["http","cache","type-mismatch","dsl"],"backgroundTag":"type-mismatch","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-16T19:17:19.609Z"}