json-path/JsonPath · error · JsonPathException

Cache provider must be configured before cache is accessed a

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.

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)

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.