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

  1. Set exactly one of resource, url, or class on each <mapper> element and remove the others
  2. 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)
  3. 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

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


AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14). Data as JSON: /api/errors/939624d96b54f846. Report an issue: GitHub.