mybatis/mybatis-3 · error · CacheException
Invalid cache decorator ({}). Cache decorators must have a
Error message
Invalid cache decorator ({}). Cache decorators must have a constructor that takes a Cache instance as a parameter. Cause: {} What it means
CacheBuilder.getCacheDecoratorConstructor() throws CacheException when a class used as a cache decorator has no public constructor taking a single Cache instance. MyBatis decorator contract requires Decorator(Cache delegate); the message names the offending class and chains the reflection failure.
Source
Thrown at src/main/java/org/apache/ibatis/mapping/CacheBuilder.java:214
+ "Base cache implementations must have a constructor that takes a String id as a parameter. Cause: " + e,
e);
}
}
private Cache newCacheDecoratorInstance(Class<? extends Cache> cacheClass, Cache base) {
Constructor<? extends Cache> cacheConstructor = getCacheDecoratorConstructor(cacheClass);
try {
return cacheConstructor.newInstance(base);
} catch (Exception e) {
throw new CacheException("Could not instantiate cache decorator (" + cacheClass + "). Cause: " + e, e);
}
}
private Constructor<? extends Cache> getCacheDecoratorConstructor(Class<? extends Cache> cacheClass) {
try {
return cacheClass.getConstructor(Cache.class);
} catch (Exception e) {
throw new CacheException("Invalid cache decorator (" + cacheClass + "). "
+ "Cache decorators must have a constructor that takes a Cache instance as a parameter. Cause: " + e, e);
}
}
}
View on GitHub (pinned to 008069adb1)
Solutions
- Give the decorator a public constructor: public MyDecorator(Cache delegate) { this.delegate = delegate; }.
- Check you registered the right kind of class: base caches take String, decorators take Cache.
- Make the constructor public so reflection can invoke it.
Example fix
// before
public class MyDecorator implements Cache {
public MyDecorator() {} // missing Cache delegate parameter
}
// after
public class MyDecorator implements Cache {
private final Cache delegate;
public MyDecorator(Cache delegate) { this.delegate = delegate; }
} Defensive patterns
Strategy: validation
Validate before calling
// Assert decorator contract before adding it
try {
MyDecorator.class.getConstructor(Cache.class);
} catch (NoSuchMethodException e) {
throw new IllegalStateException("MyDecorator must expose public MyDecorator(Cache delegate)");
} Prevention
- Model custom decorators on MyBatis' own decorators: single public (Cache delegate) constructor.
- Never register a base cache (String-id constructor) as a decorator or vice versa.
- Reflection-smoke-test all cache-related classes in a startup self-check.
When it happens
Trigger: Adding a custom decorator via CacheBuilder.addDecorator(MyDecorator.class) or the standard decorator mechanism when MyDecorator lacks a public Cache-taking constructor (only no-arg, or extra parameters).
Common situations: Writing a decorator modeled on other frameworks' wrappers (no delegate parameter); non-public constructors; accidentally registering a base cache class (String-id constructor) as a decorator.
Related errors
- Invalid base cache implementation ({}). Base cache implemen
- Could not instantiate cache decorator ({}). Cause: {}
- cache-ref element requires a namespace attribute.
- No cache for namespace '{namespace}' could be found.
- Cache-ref not yet resolved
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/0c842cecee6c4d2a.
Report an issue: GitHub.