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

  1. Call setCache exactly once, early in application startup before any JsonPath.compile call
  2. Wrap setCache in a check or try-catch for JsonPathException and treat 'already set' as success (idempotent init)
  3. Centralize cache configuration in a single static initializer/configuration class
  4. 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

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


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)