mybatis/mybatis-3 · error · BuilderException
Cannot use both value() and name() attribute in the @CacheNa
Error message
Cannot use both value() and name() attribute in the @CacheNamespaceRef
What it means
The sibling check in parseCacheRef(): @CacheNamespaceRef has both value() set (non-void class) and a non-empty name() string. The two attributes are alternative ways to identify the referenced namespace; specifying both is ambiguous and rejected.
Source
Thrown at src/main/java/org/apache/ibatis/builder/annotation/MapperAnnotationBuilder.java:217
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);
String resultMapId = generateResultMapName(method);
applyResultMap(resultMapId, returnType, args, results, typeDiscriminator);
return resultMapId;View on GitHub (pinned to 008069adb1)
Solutions
- Keep exactly one attribute: either @CacheNamespaceRef(UserMapper.class) or @CacheNamespaceRef(name = "com.acme.UserMapper")
- Prefer the class form (value) so refactors stay compile-safe
Example fix
// before @CacheNamespaceRef(value = UserMapper.class, name = "com.acme.UserMapper") // after @CacheNamespaceRef(UserMapper.class)
Defensive patterns
Strategy: type-guard
Type guard
for (Class<?> mapper : scannedMappers) {
CacheNamespaceRef r = mapper.getAnnotation(CacheNamespaceRef.class);
if (r != null && r.value() != void.class && !r.name().isEmpty()) {
throw new IllegalStateException(mapper + " sets both value() and name() in @CacheNamespaceRef");
}
} Prevention
- Standardize on the class-based form only; forbid name= in code review
- When switching attribute styles, delete the old attribute in the same commit
When it happens
Trigger: @CacheNamespaceRef(value = UserMapper.class, name = "com.acme.UserMapper") — both attributes populated.
Common situations: Copy-paste or IDE auto-complete filling both; refactoring from name-based to class-based refs without deleting the old attribute.
Related errors
- Should be specified either value() or name() attribute in th
- 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/d7ecccea756949a3.
Report an issue: GitHub.