MyCATApache/Mycat-Server · error · ConfigException

dataNode define error ,dnNames.length must…

Error message

dataNode ${dnNamePre} define error ,dnNames.length must be=databases.length*hostStrings.length

What it means

Thrown by XMLSchemaLoader when a <dataNode> uses multi-value expansion (comma/$/- ranges) and the number of expanded names does not equal databases.length * hosts.length. Mycat builds the cartesian product of hosts and databases and needs exactly one name per combination.

Solutions

  1. Adjust the name range so dnNames.length == databases.length * hostStrings.length
  2. Keep all three attributes' expansion ranges consistent (e.g. dn$0-75, host$1-10, db$0-759 semantics per the in-code example)
  3. Simplify to a single explicit <dataNode> per node if ranges are confusing

Example fix

// before (schema.xml)
<dataNode name="dn1$0-9" dataHost="localhost$1-2" database="db1" /> <!-- 10 names vs 2 combos -->
// after
<dataNode name="dn1$0-9" dataHost="localhost1" database="db1" /> <!-- 10 names vs 10 dbs -->
Defensive patterns

Strategy: validation

Validate before calling

// verify name count == database count * host count for expanded dataNodes
String[] dn = split(dnNamePre);
if (dn.length > 1) {
    int combos = split(databaseStr).length * split(host).length;
    if (dn.length != combos)
        throw new IllegalStateException("dnNames=" + dn.length + " != " + combos);
}

Try / catch

try {
    configLoader.load();
} catch (ConfigException e) {
    if (e.getMessage().contains("dnNames.length must be")) {
        log.error("Align name range with databases.length * dataHosts.length for the expanded <dataNode>", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: E.g. name="dn1$0-9" with dataHost="host1,host2" and database="db1" producing 10 names but 2*1=2 combinations; any name range whose split length mismatches the product of database and host counts.

Common situations: Changing one range (like dn1$0-759) without updating the others; misunderstanding the host×database expansion semantics documented in the XML comments; copy-pasted expansion expressions edited partially.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

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

            Element element = (Element) list.item(i);
            String dnNamePre = element.getAttribute("name");

            String databaseStr = element.getAttribute("database");
            String host = element.getAttribute("dataHost");
            //字符串不为空
            if (empty(dnNamePre) || empty(databaseStr) || empty(host)) {
                throw new ConfigException("dataNode " + dnNamePre + " define error ,attribute can't be empty");
            }
            //dnNames(name),databases(database),hostStrings(dataHost)都可以配置多个,以',', '$', '-'区分,但是需要保证database的个数*dataHost的个数=name的个数
            //多个dataHost与多个database如果写在一个标签,则每个dataHost拥有所有database
            //例如:<dataNode name="dn1$0-75" dataHost="localhost$1-10" database="db$0-759" />
            //则为:localhost1拥有dn1$0-75,localhost2也拥有dn1$0-75(对应db$76-151)
            String[] dnNames = io.mycat.util.SplitUtil.split(dnNamePre, ',', '$', '-');
            String[] databases = io.mycat.util.SplitUtil.split(databaseStr, ',', '$', '-');
            String[] hostStrings = io.mycat.util.SplitUtil.split(host, ',', '$', '-');

            if (dnNames.length > 1 && dnNames.length != databases.length * hostStrings.length) {
                throw new ConfigException("dataNode " + dnNamePre
                        + " define error ,dnNames.length must be=databases.length*hostStrings.length");
            }
            if (dnNames.length > 1) {

                List<String[]> mhdList = mergerHostDatabase(hostStrings, databases);
                for (int k = 0; k < dnNames.length; k++) {
                    String[] hd = mhdList.get(k);
                    String dnName = dnNames[k];
                    String databaseName = hd[1];
                    String hostName = hd[0];
                    createDataNode(dnName, databaseName, hostName);
                }

            } else {
                createDataNode(dnNamePre, databaseStr, host);
            }

        }

View on GitHub (pinned to 65f8d8beb7)