baomidou/mybatis-plus · error · BuilderException
Each XMLConfigBuilder can only be used once.
Error message
Each XMLConfigBuilder can only be used once.
What it means
Thrown by MybatisXMLConfigBuilder.parse() when parse() is called a second time on the same builder instance. The builder flips its parsed flag on the first run and is single-use by design: XML and state have already been consumed, so a second parse would double-register mappers and settings.
Source
Thrown at mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/MybatisXMLConfigBuilder.java:108
public MybatisXMLConfigBuilder(Class<? extends Configuration> configClass, InputStream inputStream, String environment,
Properties props) {
this(configClass, new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);
}
private MybatisXMLConfigBuilder(Class<? extends Configuration> configClass, XPathParser parser, String environment,
Properties props) {
super(newConfig(configClass));
ErrorContext.instance().resource("SQL Mapper Configuration");
this.configuration.setVariables(props);
this.parsed = false;
this.environment = environment;
this.parser = parser;
}
public Configuration parse() {
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
private void parseConfiguration(XNode root) {
try {
// issue #117 read properties first
propertiesElement(root.evalNode("properties"));
Properties settings = settingsAsProperties(root.evalNode("settings"));
loadCustomVfsImpl(settings);
loadCustomLogImpl(settings);
typeAliasesElement(root.evalNode("typeAliases"));
pluginsElement(root.evalNode("plugins"));
objectFactoryElement(root.evalNode("objectFactory"));
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
reflectorFactoryElement(root.evalNode("reflectorFactory"));View on GitHub (pinned to bf67d90747)
Solutions
- Create a new MybatisXMLConfigBuilder (new SqlSessionFactoryBuilder().build(reader)) for each parse.
- Guard lazy initialization with a null/once check so parse() runs exactly once per builder.
- If the goal is two configurations, instantiate two builders from the same reader/resource.
Example fix
// before
private final XMLConfigBuilder builder = new XMLConfigBuilder(reader);
public SqlSessionFactory factory() { return new SqlSessionFactoryBuilder().build(builder.parse()); }
public SqlSessionFactory factoryAgain() { return new SqlSessionFactoryBuilder().build(builder.parse()); }
// after
public SqlSessionFactory factory() {
try (Reader r = getResourceAsReader("mybatis-config.xml")) {
return new SqlSessionFactoryBuilder().build(r);
}
} Defensive patterns
Strategy: type-guard
Type guard
// guard: track parse state per builder
if (builder != null && !parsedOnce) {
configuration = builder.parse();
parsedOnce = true;
} Try / catch
Catch BuilderException 'Each XMLConfigBuilder can only be used once' as a signal of an initialization bug; instantiate a fresh builder (or SqlSessionFactoryBuilder().build(reader)) instead of retrying.
Prevention
- Treat builders as single-use; create them inside the factory method.
- Use double-checked locking or holder idiom for lazy SqlSessionFactory singletons.
When it happens
Trigger: Holding a MybatisXMLConfigBuilder (or SqlSessionFactoryBuilder flow that wraps it) and calling parse() twice: builder.parse(); ... builder.parse();
Common situations: Reusing a cached builder in a lazily-initialized singleton without a guard; copy-pasted initialization code paths both parsing the same builder; retry logic that re-invokes parse() after a partial failure.
Related errors
- No environment specified.
- Error parsing SQL Mapper Configuration. Cause: %s
- The setting %s is not known. Make sure you spelled it corre
- The properties element cannot specify both a URL and a resou
- Environment declaration requires a TransactionFactory.
AI-assisted analysis of baomidou/mybatis-plus@bf67d90747 (2026-08-14).
Data as JSON: /api/errors/022c0a993cdbd589.
Report an issue: GitHub.