mybatis/mybatis-3 · error · BuilderException
If there is no type discriminator, then the NamedResultMap…
Error message
If there is no type discriminator, then the NamedResultMap annotation requires at least one constructor argument or property mapping
What it means
Thrown by MapperAnnotationBuilder.validateNamedResultMap(): a @NamedResultMap annotation declares neither a type discriminator nor any constructorArguments() nor propertyMappings(). Without at least one mapping (or a discriminator to route types), the named result map would carry no column-to-property information and is rejected as a configuration error.
Solutions
- Add at least one @Arg in constructorArguments or @Property in propertyMappings to the @NamedResultMap
- Or add a typeDiscriminator so the map routes among subtypes
- If you only wanted automapping by resultType, drop @NamedResultMap entirely and use resultType on the statement
Example fix
// before @NamedResultMap(id = "userMap") // after @NamedResultMap(id = "userMap", propertyMappings = @Property(column = "user_name", property = "userName"))
Defensive patterns
Strategy: validation
Validate before calling
for (Method m : mapper.getMethods()) {
NamedResultMap nrm = m.getAnnotation(NamedResultMap.class);
if (nrm != null && nrm.constructorArguments().length == 0
&& nrm.propertyMappings().length == 0
&& "@null@".equals(nrm.typeDiscriminator().column())) { /* default sentinel */
throw new IllegalStateException(m + " has empty @NamedResultMap");
}
} Prevention
- Only add @NamedResultMap when mappings are ready; otherwise use resultType automapping
- Add a config-load test that instantiates all mapper annotations in CI
When it happens
Trigger: @NamedResultMap(id = "userMap") with empty constructorArguments, propertyMappings, and typeDiscriminator defaulting to the NULL discriminator column.
Common situations: Adding @NamedResultMap intending to reuse it via @ResultMap before filling in mappings; misunderstanding that the annotation requires explicit mappings (unlike automapping); leftover stub annotation after removing mappings.
Related errors
- A query was run and no Result Maps were found for the…
- Cannot use both @One and @Many annotations in the same…
- Cannot use both value() and name() attribute in the…
- Error in result map ' '. We do not support partially…
- Mapping is missing column attribute for property
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/93e1323b1715cce0.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/org/apache/ibatis/builder/annotation/MapperAnnotationBuilder.java:266
String resultMapId = type.getName() + '.' + namedResultMap.id();
Class<?> returnType = namedResultMap.javaType();
Arg[] args = namedResultMap.constructorArguments();
Result[] results = namedResultMap.propertyMappings();
TypeDiscriminator typeDiscriminator = namedResultMap.typeDiscriminator();
if (AnnotationConstants.NULL_TYPE_DISCRIMINATOR.equals(typeDiscriminator.column())) {
typeDiscriminator = null;
}
applyResultMap(resultMapId, returnType, args, results, typeDiscriminator);
}
private void validateNamedResultMap(NamedResultMap namedResultMap) {
if (!AnnotationConstants.NULL_TYPE_DISCRIMINATOR.equals(namedResultMap.typeDiscriminator().column())) {
return;
}
if (namedResultMap.constructorArguments().length == 0 && namedResultMap.propertyMappings().length == 0) {
throw new BuilderException("If there is no type discriminator, then the NamedResultMap annotation "
+ "requires at least one constructor argument or property mapping");
}
}
private String generateResultMapName(Method method) {
Results results = method.getAnnotation(Results.class);
if (results != null && !results.id().isEmpty()) {
return type.getName() + "." + results.id();
}
StringBuilder suffix = new StringBuilder();
for (Class<?> c : method.getParameterTypes()) {
suffix.append("-");
suffix.append(c.getSimpleName());
}
if (suffix.length() < 1) {
suffix.append("-void");
}
return type.getName() + "." + method.getName() + suffix;View on GitHub (pinned to 008069adb1)