MyCATApache/Mycat-Server · error · ConfigException

table duplicated!

Error message

table ${table.getName()} duplicated!

What it means

Thrown by XMLSchemaLoader's child-table processing (processChildTables, called recursively from the constructor) when a child <table> in a parent/child (ER) sharding setup has the same name as a table already registered. Child tables are also keyed by name in the tables map, so duplicates are rejected at load.

Solutions

  1. Give the childTable a unique name distinct from all other tables and child tables
  2. Remove the duplicate childTable element from schema.xml
  3. Verify the parent/child table hierarchy has unique names at every level

Example fix

// before (schema.xml)
<childTable name="orders" joinKey="cid" parentKey="id" />
// after
<childTable name="order_items" joinKey="cid" parentKey="id" />
Defensive patterns

Strategy: validation

Validate before calling

// collect parent + childTable names and ensure uniqueness before load
Set<String> names = new HashSet<>();
for (Element t : schemaTables("schema.xml")) {
    addAllTableNames(names, t); // includes nested <childTable> recursively
}
if (names.size() != totalCount) throw new IllegalStateException("Duplicate child table name");

Try / catch

try {
    configLoader.load();
} catch (ConfigException e) {
    if (e.getMessage().contains("duplicated!")) {
        log.error("Child table name collides with an existing table/childTable in schema.xml", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: A nested <childTable name="..."> (or recursive child-of-child) whose name equals a table already present in the tables map, including a child table colliding with its parent or sibling.

Common situations: Copy-pasted childTable blocks with the same name; child table name accidentally matching a normal table; deep sub-table recursion reusing names.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


AI-assisted analysis of MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11). Data as JSON: /api/errors/ea47558130c825b1. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/io/mycat/config/loader/xml/XMLSchemaLoader.java:550

                autoIncrement = Boolean.parseBoolean(childTbElement.getAttribute("autoIncrement"));
            }
            boolean needAddLimit = true;
            if (childTbElement.hasAttribute("needAddLimit")) {
                needAddLimit = Boolean.parseBoolean(childTbElement.getAttribute("needAddLimit"));
            }

            String subTables = childTbElement.getAttribute("subTables");
            //子表join键,和对应的parent的键,父子表通过这个关联
            String joinKey = childTbElement.getAttribute("joinKey").toUpperCase();
            String parentKey = childTbElement.getAttribute("parentKey").toUpperCase();
            TableConfig table = new TableConfig(cdTbName, primaryKey,
                    autoIncrement, needAddLimit,
                    TableConfig.TYPE_GLOBAL_DEFAULT, dataNodes,
                    getDbType(dataNodes), null, false, parentTable, true,
                    joinKey, parentKey, subTables, false);

            if (tables.containsKey(table.getName())) {
                throw new ConfigException("table " + table.getName() + " duplicated!");
            }
            tables.put(table.getName(), table);
            //对于子表的子表,递归处理
            processChildTables(tables, table, dataNodes, childTbElement);
        }
    }

    private void checkDataNodeExists(Collection<String> nodes) {
        if (nodes == null || nodes.size() < 1) {
            return;
        }
        for (String node : nodes) {
            if (!dataNodes.containsKey(node)) {
                throw new ConfigException("dataNode '" + node + "' is not found!");
            }
        }
    }

View on GitHub (pinned to 65f8d8beb7)