mybatis/mybatis-3 · error · BuilderException
Should be specified either value() or name() attribute in th
Error message
Should be specified either value() or name() attribute in the @CacheNamespaceRef
What it means
Thrown by MapperAnnotationBuilder.parseCacheRef() when @CacheNamespaceRef is present but both attributes are unset: value() defaults to void.class and name() defaults to "". The annotation must say which namespace to borrow the cache from, via either the mapper class (value) or a string namespace (name).
Source
Thrown at src/main/java/org/apache/ibatis/builder/annotation/MapperAnnotationBuilder.java:214
private Properties convertToProperties(Property[] properties) {
if (properties.length == 0) {
return null;
}
Properties props = new Properties();
for (Property property : properties) {
props.setProperty(property.name(), PropertyParser.parse(property.value(), configuration.getVariables()));
}
return props;
}
private void parseCacheRef() {
CacheNamespaceRef cacheDomainRef = type.getAnnotation(CacheNamespaceRef.class);
if (cacheDomainRef != null) {
Class<?> refType = cacheDomainRef.value();
String refName = cacheDomainRef.name();
if (refType == void.class && refName.isEmpty()) {
throw new BuilderException("Should be specified either value() or name() attribute in the @CacheNamespaceRef");
}
if (refType != void.class && !refName.isEmpty()) {
throw new BuilderException("Cannot use both value() and name() attribute in the @CacheNamespaceRef");
}
String namespace = refType != void.class ? refType.getName() : refName;
try {
assistant.useCacheRef(namespace);
} catch (IncompleteElementException e) {
configuration.addIncompleteCacheRef(new CacheRefResolver(assistant, namespace));
}
}
}
private String parseResultMap(Method method) {
Class<?> returnType = getReturnType(method, type);
Arg[] args = method.getAnnotationsByType(Arg.class);
Result[] results = method.getAnnotationsByType(Result.class);
TypeDiscriminator typeDiscriminator = method.getAnnotation(TypeDiscriminator.class);View on GitHub (pinned to 008069adb1)
Solutions
- Point the ref at the cache-owning mapper: @CacheNamespaceRef(UserMapper.class)
- Or use the string form: @CacheNamespaceRef(name = "com.acme.UserMapper")
- Confirm the referenced class declares @CacheNamespace (a ref to a mapper without a cache fails later with the incomplete-cache error)
Example fix
// before
@CacheNamespaceRef
public interface OrderMapper { ... }
// after
@CacheNamespaceRef(UserMapper.class)
public interface OrderMapper { ... } Defensive patterns
Strategy: type-guard
Type guard
// Compile-time guard: a wrapper annotation forcing an attribute
@Retention(RetentionPolicy.SOURCE)
public @interface CacheRefTarget {
Class<?> value() default void.class;
String name() default "";
}
// runtime check before SqlSessionFactory build:
for (Class<?> mapper : scannedMappers) {
CacheNamespaceRef r = mapper.getAnnotation(CacheNamespaceRef.class);
if (r != null && r.value() == void.class && r.name().isEmpty()) {
throw new IllegalStateException(mapper + " has @CacheNamespaceRef without value/name");
}
} Prevention
- Always write @CacheNamespaceRef with an explicit target; never rely on defaults
- Prefer the class form @CacheNamespaceRef(OtherMapper.class) so a missing target breaks compilation
When it happens
Trigger: Writing @CacheNamespaceRef with no attributes on a mapper interface; defaults (void.class, empty string) fail the check.
Common situations: Assuming @CacheNamespaceRef works standalone like @CacheNamespace does; forgetting the target after refactoring; IDE auto-import picking the annotation without suggesting required attributes.
Related errors
- Cannot use both value() and name() attribute in the @CacheNa
- cache-ref element requires a namespace attribute.
- If there is no type discriminator, then the NamedResultMap a
- Error building standard cache decorators. Cause: {}
- Unsupported property type for cache: '{}' of type {}
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/e09c623ff96f381c.
Report an issue: GitHub.