mybatis/mybatis-3 · error · BuilderException

Error in result map '{resultMapId}'. We do not support parti

Error message

Error in result map '{resultMapId}'. We do not support partially specifying a property name nor duplicates. Either specify all property names, or none.

What it means

Thrown by ResultMappingConstructorResolver.verifyPropertyNaming(): within a <constructor> mapping, some (but not all) <arg> elements carry a name attribute, or duplicates exist, so the count of collected names differs from the number of constructor mappings. MyBatis requires name attributes on either all args (name-based matching) or none (type/order-based matching), never a mix.

Source

Thrown at src/main/java/org/apache/ibatis/builder/ResultMappingConstructorResolver.java:158

    final List<ResultMapping> resultMappings = autoTypeRequired
        ? autoTypeConstructorMappings(matchingConstructorInfo, constructorResultMappings, allMappingsHavePropertyNames)
        : constructorResultMappings;

    if (allMappingsHavePropertyNames) {
      // finally sort them based on the constructor meta info
      sortConstructorMappings(matchingConstructorInfo, resultMappings);
    }

    return resultMappings;
  }

  private boolean verifyPropertyNaming(Set<String> constructorArgsByName) {
    final boolean allMappingsHavePropertyNames = constructorResultMappings.size() == constructorArgsByName.size();

    // If property names have been partially specified, throw an exception, as this case does not make sense
    // either specify all names and (optional random order), or type info.
    if (!allMappingsHavePropertyNames && !constructorArgsByName.isEmpty()) {
      throw new BuilderException("Error in result map '" + resultMapId
          + "'. We do not support partially specifying a property name nor duplicates. Either specify all property names, or none.");
    }

    return allMappingsHavePropertyNames;
  }

  List<ConstructorMetaInfo> retrieveConstructorCandidates(int withLength) {
    return Arrays.stream(resultType.getDeclaredConstructors())
        .filter(constructor -> constructor.getParameterTypes().length == withLength).map(ConstructorMetaInfo::new)
        .collect(Collectors.toList());
  }

  private static void removeCandidatesBasedOnParameterNames(List<ConstructorMetaInfo> matchingConstructorCandidates,
      Set<String> constructorArgsByName) {
    final Iterator<ConstructorMetaInfo> candidateIterator = matchingConstructorCandidates.iterator();
    while (candidateIterator.hasNext()) {
      // extract the names (and types) the constructor has
      final ConstructorMetaInfo candidateInfo = candidateIterator.next();

View on GitHub (pinned to 008069adb1)

Solutions

  1. Either add name attributes to every <arg> in the constructor block, or remove them all
  2. Ensure names are unique across args in the same constructor
  3. When going name-less, supply javaType on each arg so positional/type matching still works

Example fix

<!-- before -->
<constructor>
  <arg column="id" name="id"/>
  <arg column="user_name"/>
</constructor>
<!-- after -->
<constructor>
  <arg column="id" name="id"/>
  <arg column="user_name" name="userName"/>
</constructor>
Defensive patterns

Strategy: validation

Validate before calling

// XML-side check: within <constructor>, either all <arg> have name or none, and names unique
Element ctor = (Element) resultMapEl.getElementsByTagName("constructor").item(0);
if (ctor != null) {
  List<Element> args = asList(ctor.getElementsByTagName("arg"));
  long named = args.stream().filter(a -> a.hasAttribute("name")).count();
  Set<String> names = args.stream().filter(a -> a.hasAttribute("name"))
      .map(a -> a.getAttribute("name")).collect(Collectors.toSet());
  if (named != 0 && named != args.size()) throw new IllegalStateException("Mixed named/unnamed constructor args");
  if (names.size() != named) throw new IllegalStateException("Duplicate constructor arg names");
}

Prevention

When it happens

Trigger: <constructor><arg column="a" name="x"/><arg column="b"/></constructor> — one arg named, the other anonymous; or two args with the same name (the Set used for names shrinks the count and trips the same check).

Common situations: Incrementally adding a new <arg> to an existing constructor mapping and forgetting its name; copy-paste leaving duplicate names; merging mapper changes where naming style differs.

Related errors


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