mybatis/mybatis-3 · error · BuilderException
A mapper element may only specify a url, resource or class,
Error message
A mapper element may only specify a url, resource or class, but not more than one.
What it means
Thrown while parsing the <mappers> section of mybatis-config.xml when a single <mapper> element does not specify exactly one of the attributes resource, url, or class. The parser branches on which combination is present; the final else branch catches both 'none specified' and 'more than one specified' with this single message. It is a configuration-format error raised at SqlSessionFactoryBuilder build time, before any session is opened.
Source
Thrown at src/main/java/org/apache/ibatis/builder/xml/XMLConfigBuilder.java:418
if (resource != null && url == null && mapperClass == null) {
ErrorContext.instance().resource(resource);
try (InputStream inputStream = Resources.getResourceAsStream(resource)) {
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource,
configuration.getSqlFragments());
mapperParser.parse();
}
} else if (resource == null && url != null && mapperClass == null) {
ErrorContext.instance().resource(url);
try (InputStream inputStream = Resources.getUrlAsStream(url)) {
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url,
configuration.getSqlFragments());
mapperParser.parse();
}
} else if (resource == null && url == null && mapperClass != null) {
Class<?> mapperInterface = Resources.classForName(mapperClass);
configuration.addMapper(mapperInterface);
} else {
throw new BuilderException(
"A mapper element may only specify a url, resource or class, but not more than one.");
}
}
}
}
private boolean isSpecifiedEnvironment(String id) {
if (environment == null) {
throw new BuilderException("No environment specified.");
}
if (id == null) {
throw new BuilderException("Environment requires an id attribute.");
}
return environment.equals(id);
}
private static Configuration newConfig(Class<? extends Configuration> configClass) {
try {View on GitHub (pinned to 008069adb1)
Solutions
- Set exactly one of resource, url, or class on each <mapper> element and remove the others
- If no attribute is set, add the one you intended (class='com.acme.UserMapper' for interface mappers, resource='path/in/classpath/UserMapper.xml' for XML files)
- Use <package name="com.acce.mappers"/> instead of many <mapper class=.../> entries when registering a whole package
Example fix
<!-- before --> <mapper resource="mappers/UserMapper.xml" class="com.acme.UserMapper"/> <!-- after --> <mapper resource="mappers/UserMapper.xml"/>
Defensive patterns
Strategy: validation
Validate before calling
for (Element m : mapperElements) {
int specified = Stream.of("resource","url","class")
.map(a -> m.getAttribute(a)).filter(a -> !a.isEmpty()).toArray().length;
if (specified != 1) throw new IllegalStateException("<mapper> at " + location + " must set exactly one of resource/url/class, found " + specified);
} Try / catch
catch (BuilderException e) when starting up: fail fast and report the mapper element; config errors are not recoverable at runtime — fix the XML.
Prevention
- Validate mybatis-config.xml against mybatis-3-config.xsd in CI
- Use <package> registration for bulk mapper packages
When it happens
Trigger: A <mapper/> element with (a) no attributes at all, (b) two or all three of resource/url/class set, e.g. <mapper resource="mappers/User.xml" class="com.acme.UserMapper"/>. Raised from XMLConfigBuilder.mapperElement() during new SqlSessionFactoryBuilder().build(reader).
Common situations: Copy-pasting mapper entries and forgetting to delete the old attribute; migrating from XML mappers to annotation/class mappers and leaving resource behind; typos in attribute names (e.g. 'resouce') so the real attribute is never read and all three read as null, producing the same error via the 'none specified' path.
Related errors
- No environment specified.
- Environment requires an id attribute.
- name + " already contains key " + key
- Unknown execution method for: {name}
- Mapper method '{name}' attempted to return null from a metho
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/939624d96b54f846.
Report an issue: GitHub.