{"record":{"id":"e5b63aa35b9455b5","repo":"redis/jedis","slug":"failed-to-find-compatible-constructor-for-custom-c","errorCode":null,"errorMessage":"Failed to find compatible constructor for custom cache type!  Provide one of these;\n - ${className}(int maxSize, EvictionPolicy evictionPolicy)\n - ${className}(int maxSize, EvictionPolicy evictionPolicy, Cacheable cacheable)","messagePattern":"Failed to find compatible constructor for custom cache type!  Provide one of these;\n - (.+?)\\(int maxSize, EvictionPolicy evictionPolicy\\)\n - (.+?)\\(int maxSize, EvictionPolicy evictionPolicy, Cacheable cacheable\\)","errorType":"exception","errorClass":"JedisCacheException","httpStatus":null,"severity":"error","filePath":"src/main/java/redis/clients/jedis/csc/CacheFactory.java","lineNumber":48,"sourceCode":"            return (Cache) ctor.newInstance(config.getMaxSize(), getEvictionPolicy(config));\n        } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException\n                | SecurityException e) {\n            throw new JedisCacheException(\"Failed to insantiate custom cache type!\", e);\n        }\n    }\n\n    private static Constructor findConstructorWithCacheable(Class customCacheType) {\n        return Arrays.stream(customCacheType.getConstructors())\n                .filter(ctor -> Arrays.equals(ctor.getParameterTypes(), new Class[] { int.class, EvictionPolicy.class, Cacheable.class }))\n                .findFirst().orElse(null);\n    }\n\n    private static Constructor getConstructor(Class customCacheType) {\n        try {\n            return customCacheType.getConstructor(int.class, EvictionPolicy.class);\n        } catch (NoSuchMethodException e) {\n            String className = customCacheType.getName();\n            throw new JedisCacheException(String.format(\n                \"Failed to find compatible constructor for custom cache type!  Provide one of these;\"\n                        // give hints about the compatible constructors\n                        + \"\\n - %s(int maxSize, EvictionPolicy evictionPolicy)\\n - %s(int maxSize, EvictionPolicy evictionPolicy, Cacheable cacheable)\",\n                className, className), e);\n        }\n    }\n\n    private static EvictionPolicy getEvictionPolicy(CacheConfig config) {\n        if (config.getEvictionPolicy() == null) {\n            // It will be default to LRUEviction, until we have other eviction implementations\n            return new LRUEviction(config.getMaxSize());\n        }\n        return config.getEvictionPolicy();\n    }\n}","sourceCodeStart":30,"sourceCodeEnd":63,"githubUrl":"https://github.com/redis/jedis/blob/6dac31d4c224fb3257c216f3985340c6f500cdcb/src/main/java/redis/clients/jedis/csc/CacheFactory.java#L30-L63","documentation":"getConstructor looks for a public constructor matching (int, EvictionPolicy) on the configured custom cache class; if absent, it throws JedisCacheException listing the two accepted constructor signatures — with or without a trailing Cacheable parameter. This tells the developer their custom Cache class does not expose a constructor shape CacheFactory can invoke.","triggerScenarios":"config.setCacheClass(X.class) where X has no public constructor of shape (int maxSize, EvictionPolicy) or (int maxSize, EvictionPolicy, Cacheable) — e.g. only a no-arg constructor, only builders, or the 2-arg constructor is private/protected.","commonSituations":"Implementing a custom cache with dependency injection (no matching constructor); wrapping a third-party cache (e.g. Caffeine) whose constructors have different parameters; forgetting that the (int, EvictionPolicy, Cacheable) hint only works if findConstructorWithCacheable's path applies.","solutions":["Add a public constructor X(int maxSize, EvictionPolicy evictionPolicy) to your custom cache class.","Alternatively add X(int maxSize, EvictionPolicy evictionPolicy, Cacheable cacheable) so the cacheable-aware path can be used.","If you cannot change the constructor, adapt with a thin subclass exposing the required (int, EvictionPolicy) constructor.","Verify the class is public and the constructor is public (non-public constructors are invisible to getConstructor)."],"exampleFix":"// before\npublic class MyCache implements Cache {\n  public MyCache() { ... } // no matching constructor\n}\n// after\npublic class MyCache implements Cache {\n  public MyCache(int maxSize, EvictionPolicy evictionPolicy) { ... }\n}","handlingStrategy":"validation","validationCode":"static void requireCompatibleCacheCtor(Class<? extends Cache> type) {\n  boolean ok = Arrays.stream(type.getConstructors()).anyMatch(c ->\n      Arrays.equals(c.getParameterTypes(), new Class[]{int.class, EvictionPolicy.class}) ||\n      Arrays.equals(c.getParameterTypes(), new Class[]{int.class, EvictionPolicy.class, Cacheable.class}));\n  if (!ok) throw new IllegalArgumentException(type.getName() +\n      \" must expose public (int, EvictionPolicy) or (int, EvictionPolicy, Cacheable) constructor\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  Cache cache = CacheFactory.getCache(config);\n} catch (JedisCacheException e) {\n  if (e.getMessage().contains(\"Failed to find compatible constructor\")) {\n    // add or expose the required constructor in the custom cache class\n  } else throw e;\n}","preventionTips":["Give every custom Cache class a public (int maxSize, EvictionPolicy) constructor as a convention","Do not rely on builder/factory patterns as the only construction path for cacheClass","Write a unit test asserting the constructor signature exists before wiring it into CacheConfig"],"tags":["reflection","cache","constructor-signature"],"backgroundTag":"invalid-constructor-argument","analyzedSha":"6dac31d4c224fb3257c216f3985340c6f500cdcb","analyzedAt":"2026-09-08T04:55:01.204Z","contentChangedAt":"2026-09-08T04:55:01.204Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}