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

  1. Give the decorator a public constructor: public MyDecorator(Cache delegate) { this.delegate = delegate; }.
  2. Check you registered the right kind of class: base caches take String, decorators take Cache.
  3. 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

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


AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14). Data as JSON: /api/errors/0c842cecee6c4d2a. Report an issue: GitHub.