json-path/JsonPath · error · JsonPathException
Cache provider must be configured before cache is accessed…
Error message
Cache provider must be configured before cache is accessed and must not be registered twice.
What it means
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.
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
Example fix
// before
CacheProvider.setCache(new LRUCache(400));
// after
try {
CacheProvider.setCache(new LRUCache(400));
} catch (JsonPathException e) {
// cache already configured; keep existing instance
} Defensive patterns
Strategy: try-catch
Validate before calling
// no pre-check API exists; guard with idempotent init private static final AtomicBoolean CACHE_SET = new AtomicBoolean(false); if (CACHE_SET.compareAndSet(false, true)) CacheProvider.setCache(cache);
Try / catch
try {
CacheProvider.setCache(new LRUCache(400));
} catch (JsonPathException e) {
// already configured — treat as success
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
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
- Add can not be performed to multiple properties
- Aggregation function attempted to calculate value using…
- Aggregation function attempted to calculate value using…
- an array or object instance is expected
- Arguments to function: '' are not closed properly.
AI-assisted analysis of json-path/JsonPath@62a4c9f0f6 (2026-09-11).
Data as JSON: /api/errors/4060ee70f1943e70.
Report an issue: GitHub.
Appendix: source
Thrown at json-path/src/main/java/com/jayway/jsonpath/spi/cache/CacheProvider.java:40
// and if no external implementation has been registered,
// we need to initialise it to the default LRUCache
if (cache == null) {
cache = getDefaultCache();
// on the off chance that the cache implementation was registered during
// initialisation of the holder, this should be respected, so if the
// default cache can't be written back, just read the user supplied value again
if (!UPDATER.compareAndSet(instance, null, cache)) {
cache = CacheProvider.instance.cache;
}
}
CACHE = cache;
}
}
public static void setCache(Cache cache){
notNull(cache, "Cache may not be null");
if (!UPDATER.compareAndSet(instance, null, cache)) {
throw new JsonPathException("Cache provider must be configured before cache is accessed and must not be registered twice.");
}
}
public static Cache getCache() {
return CacheHolder.CACHE;
}
private static Cache getDefaultCache(){
return new LRUCache(400);
//return new NOOPCache();
}
}
View on GitHub (pinned to 62a4c9f0f6)