{"record":{"id":"4060ee70f1943e70","repo":"json-path/JsonPath","slug":"cache-provider-must-be-configured-before-cache-is","errorCode":null,"errorMessage":"Cache provider must be configured before cache is accessed and must not be registered twice.","messagePattern":"Cache provider must be configured before cache is accessed and must not be registered twice\\.","errorType":"exception","errorClass":"JsonPathException","httpStatus":null,"severity":"error","filePath":"json-path/src/main/java/com/jayway/jsonpath/spi/cache/CacheProvider.java","lineNumber":40,"sourceCode":"            // and if no external implementation has been registered,\n            // we need to initialise it to the default LRUCache\n            if (cache == null) {\n                cache = getDefaultCache();\n                // on the off chance that the cache implementation was registered during\n                // initialisation of the holder, this should be respected, so if the\n                // default cache can't be written back, just read the user supplied value again\n                if (!UPDATER.compareAndSet(instance, null, cache)) {\n                    cache = CacheProvider.instance.cache;\n                }\n            }\n            CACHE = cache;\n        }\n    }\n\n    public static void setCache(Cache cache){\n        notNull(cache, \"Cache may not be null\");\n        if (!UPDATER.compareAndSet(instance, null, cache)) {\n            throw new JsonPathException(\"Cache provider must be configured before cache is accessed and must not be registered twice.\");\n        }\n    }\n\n    public static Cache getCache() {\n        return CacheHolder.CACHE;\n    }\n\n\n    private static Cache getDefaultCache(){\n        return new LRUCache(400);\n        //return new NOOPCache();\n    }\n}\n","sourceCodeStart":22,"sourceCodeEnd":54,"githubUrl":"https://github.com/json-path/JsonPath/blob/62a4c9f0f65ba3f625aa0867d64c528ba72d09ec/json-path/src/main/java/com/jayway/jsonpath/spi/cache/CacheProvider.java#L22-L54","documentation":"CacheProvider.setCache installs the process-wide Cache used by JsonPath for compiled-path caching. It enforces two invariants: the cache may not be null and it can only be set once. If getCache()/CacheHolder was already touched (triggering the default cache) or setCache was called twice, the CAS update fails and this JsonPathException is thrown.","triggerScenarios":"Calling CacheProvider.setCache(cache) more than once (e.g. in two config classes, tests, or on app restart within the same JVM); calling any JsonPath.compile before installing a custom cache so the default is already initialized, then trying to setCache; concurrent framework init (Spring context + manual init) both registering a cache.","commonSituations":"Two @Configuration beans both configuring caching; unit tests where one test sets a cache and a later test tries to set another; library auto-initialization racing explicit configuration in application startup code.","solutions":["Call setCache exactly once, early in application startup before any JsonPath.compile call","Wrap setCache in a check or try-catch for JsonPathException and treat 'already set' as success (idempotent init)","Centralize cache configuration in a single static initializer/configuration class","If a different cache must be installed, the only supported route is ensuring the first registration never happened — restructure code so only one site registers"],"exampleFix":"// before\nCacheProvider.setCache(new LRUCache(400));\n// after\ntry {\n    CacheProvider.setCache(new LRUCache(400));\n} catch (JsonPathException e) {\n    // cache already configured; keep existing instance\n}","handlingStrategy":"try-catch","validationCode":"// no pre-check API exists; guard with idempotent init\nprivate static final AtomicBoolean CACHE_SET = new AtomicBoolean(false);\nif (CACHE_SET.compareAndSet(false, true)) CacheProvider.setCache(cache);","typeGuard":null,"tryCatchPattern":"try {\n    CacheProvider.setCache(new LRUCache(400));\n} catch (JsonPathException e) {\n    // already configured — treat as success\n}","preventionTips":["Configure the cache once at startup, before any JsonPath.compile","Centralize cache registration in one configuration class","Make init idempotent with a flag/compareAndSet","Avoid touching JsonPath in static initializers of multiple classes"],"tags":["json-path","cache","initialization"],"backgroundTag":"invalid-state-transition","analyzedSha":"62a4c9f0f65ba3f625aa0867d64c528ba72d09ec","analyzedAt":"2026-09-11T11:36:00.448Z","contentChangedAt":"2026-09-11T11:36:00.448Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}