MyCATApache/Mycat-Server · error · ConfigException

dataNode define error ,attribute can't be empty

Error message

dataNode ${dnNamePre} define error ,attribute can't be empty

What it means

Thrown by XMLSchemaLoader when parsing a <dataNode> element whose required attributes (name, database, or dataHost) are missing or empty. Each dataNode must identify a name, a physical database, and a dataHost to be usable.

Solutions

  1. Add non-empty name, database, and dataHost attributes to the offending <dataNode> element in schema.xml
  2. Validate the XML against the expected dataNode structure before startup
  3. Check for template placeholders that were never substituted

Example fix

// before (schema.xml)
<dataNode name="dn1" database="" dataHost="localhost1" />
// after
<dataNode name="dn1" dataHost="localhost1" database="db1" />
Defensive patterns

Strategy: validation

Validate before calling

// ensure dataNode elements have all required attributes
for (Element dn : dataNodeElements("schema.xml")) {
    for (String attr : new String[]{"name", "database", "dataHost"}) {
        if (dn.getAttribute(attr).trim().isEmpty())
            throw new IllegalStateException("<dataNode> missing attribute: " + attr);
    }
}

Try / catch

try {
    configLoader.load();
} catch (ConfigException e) {
    if (e.getMessage().contains("define error ,attribute can't be empty")) {
        String name = extractBetween(e.getMessage(), "dataNode ", " define error");
        log.error("<dataNode name='" + name + "'> is missing name/database/dataHost", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: A <dataNode database="db1" dataHost="host1" /> without name, or name present but database/dataHost attribute empty, in schema.xml.

Common situations: Hand-edited or generated schema.xml dropping an attribute; XML templates with unfilled placeholders (name=""); copy-paste errors creating incomplete dataNode entries.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

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

                                String.valueOf(tableConf.getRule().getRuleAlgorithm().getPartitionNum()),
                                String.valueOf(tableConf.getDataNodes().size())
                        });
                break;
        }
    }

    private void loadDataNodes(Element root) {
        //读取DataNode分支
        NodeList list = root.getElementsByTagName("dataNode");
        for (int i = 0, n = list.getLength(); i < n; i++) {
            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);

View on GitHub (pinned to 65f8d8beb7)