mybatis/mybatis-3 · error · BuilderException

Variable {name} defined twice in the same include definition

Error message

Variable {name} defined twice in the same include definition

What it means

Thrown by XMLIncludeTransformer when parsing the <property> children of an <include> element: the same variable name is declared twice within one include definition. Each child element's name/value becomes an entry in the include's variable context, and a duplicate put() is rejected immediately at parse time.

Source

Thrown at src/main/java/org/apache/ibatis/builder/xml/XMLIncludeTransformer.java:132

   * @param inheritedVariablesContext
   *          Current context used for replace variables in new variables values
   *
   * @return variables context from include instance (no inherited values)
   */
  private Properties getVariablesContext(Node node, Properties inheritedVariablesContext) {
    Map<String, String> declaredProperties = null;
    NodeList children = node.getChildNodes();
    for (int i = 0; i < children.getLength(); i++) {
      Node n = children.item(i);
      if (n.getNodeType() == Node.ELEMENT_NODE) {
        String name = getStringAttribute(n, "name");
        // Replace variables inside
        String value = PropertyParser.parse(getStringAttribute(n, "value"), inheritedVariablesContext);
        if (declaredProperties == null) {
          declaredProperties = new HashMap<>();
        }
        if (declaredProperties.put(name, value) != null) {
          throw new BuilderException("Variable " + name + " defined twice in the same include definition");
        }
      }
    }
    if (declaredProperties == null) {
      return inheritedVariablesContext;
    }
    Properties newProperties = new Properties();
    newProperties.putAll(inheritedVariablesContext);
    newProperties.putAll(declaredProperties);
    return newProperties;
  }
}

View on GitHub (pinned to 008069adb1)

Solutions

  1. Remove the duplicate <property> so each name appears exactly once inside the include
  2. If two values are genuinely needed, rename one of the properties and update the ${placeholder} in the referenced <sql> fragment
  3. Grep the mapper for '<property name="<dupName>"' to catch all copies

Example fix

<!-- before -->
<include refid="cols">
  <property name="alias" value="u"/>
  <property name="alias" value="o"/>
</include>

<!-- after -->
<include refid="cols">
  <property name="alias" value="u"/>
</include>
Defensive patterns

Strategy: validation

Validate before calling

Set<String> seen = new HashSet<>();
for (Element p : includePropertyChildren) {
  if (!seen.add(p.getAttribute("name")))
    throw new IllegalStateException("duplicate include property: " + p.getAttribute("name"));
}

Prevention

When it happens

Trigger: <include refid="..."><property name="col" value="a"/><property name="col" value="b"/></include> — two <property> elements with identical name attributes inside the same <include>.

Common situations: Copy-pasting a property line to tweak the value and leaving both copies; refactoring a shared include's parameters; hand-merging mapper XML during conflict resolution keeping both sides' property lines.

Related errors


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