{"record":{"id":"77240f91c4612dc5","repo":"MyCATApache/Mycat-Server","slug":"datanode-dnnamepre-define-error-dnnames-length","errorCode":null,"errorMessage":"dataNode ${dnNamePre} define error ,dnNames.length must be=databases.length*hostStrings.length","messagePattern":"dataNode (.+?) define error ,dnNames\\.length must be=databases\\.length\\*hostStrings\\.length","errorType":"exception","errorClass":"ConfigException","httpStatus":null,"severity":"error","filePath":"src/main/java/io/mycat/config/loader/xml/XMLSchemaLoader.java","lineNumber":634,"sourceCode":"            Element element = (Element) list.item(i);\n            String dnNamePre = element.getAttribute(\"name\");\n\n            String databaseStr = element.getAttribute(\"database\");\n            String host = element.getAttribute(\"dataHost\");\n            //字符串不为空\n            if (empty(dnNamePre) || empty(databaseStr) || empty(host)) {\n                throw new ConfigException(\"dataNode \" + dnNamePre + \" define error ,attribute can't be empty\");\n            }\n            //dnNames（name）,databases（database）,hostStrings（dataHost）都可以配置多个，以',', '$', '-'区分，但是需要保证database的个数*dataHost的个数=name的个数\n            //多个dataHost与多个database如果写在一个标签，则每个dataHost拥有所有database\n            //例如：<dataNode name=\"dn1$0-75\" dataHost=\"localhost$1-10\" database=\"db$0-759\" />\n            //则为：localhost1拥有dn1$0-75,localhost2也拥有dn1$0-75（对应db$76-151）\n            String[] dnNames = io.mycat.util.SplitUtil.split(dnNamePre, ',', '$', '-');\n            String[] databases = io.mycat.util.SplitUtil.split(databaseStr, ',', '$', '-');\n            String[] hostStrings = io.mycat.util.SplitUtil.split(host, ',', '$', '-');\n\n            if (dnNames.length > 1 && dnNames.length != databases.length * hostStrings.length) {\n                throw new ConfigException(\"dataNode \" + dnNamePre\n                        + \" define error ,dnNames.length must be=databases.length*hostStrings.length\");\n            }\n            if (dnNames.length > 1) {\n\n                List<String[]> mhdList = mergerHostDatabase(hostStrings, databases);\n                for (int k = 0; k < dnNames.length; k++) {\n                    String[] hd = mhdList.get(k);\n                    String dnName = dnNames[k];\n                    String databaseName = hd[1];\n                    String hostName = hd[0];\n                    createDataNode(dnName, databaseName, hostName);\n                }\n\n            } else {\n                createDataNode(dnNamePre, databaseStr, host);\n            }\n\n        }","sourceCodeStart":616,"sourceCodeEnd":652,"githubUrl":"https://github.com/MyCATApache/Mycat-Server/blob/65f8d8beb752f935752f2a0eec0ab017facab9ef/src/main/java/io/mycat/config/loader/xml/XMLSchemaLoader.java#L616-L652","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Adjust the name range so dnNames.length == databases.length * hostStrings.length","Keep all three attributes' expansion ranges consistent (e.g. dn$0-75, host$1-10, db$0-759 semantics per the in-code example)","Simplify to a single explicit <dataNode> per node if ranges are confusing"],"exampleFix":"// before (schema.xml)\n<dataNode name=\"dn1$0-9\" dataHost=\"localhost$1-2\" database=\"db1\" /> <!-- 10 names vs 2 combos -->\n// after\n<dataNode name=\"dn1$0-9\" dataHost=\"localhost1\" database=\"db1\" /> <!-- 10 names vs 10 dbs -->","handlingStrategy":"validation","validationCode":"// verify name count == database count * host count for expanded dataNodes\nString[] dn = split(dnNamePre);\nif (dn.length > 1) {\n    int combos = split(databaseStr).length * split(host).length;\n    if (dn.length != combos)\n        throw new IllegalStateException(\"dnNames=\" + dn.length + \" != \" + combos);\n}","typeGuard":null,"tryCatchPattern":"try {\n    configLoader.load();\n} catch (ConfigException e) {\n    if (e.getMessage().contains(\"dnNames.length must be\")) {\n        log.error(\"Align name range with databases.length * dataHosts.length for the expanded <dataNode>\", e);\n    }\n    throw e;\n}","preventionTips":["Change all three attributes (name, database, dataHost) together when adjusting expansion ranges","Note the expansion rule: names count must equal hosts × databases","Prefer many explicit <dataNode> elements over ranges when the math is error-prone"],"tags":["config","xml","datanode","expansion-mismatch"],"backgroundTag":"invalid-argument-format","analyzedSha":"65f8d8beb752f935752f2a0eec0ab017facab9ef","analyzedAt":"2026-09-11T00:12:21.696Z","contentChangedAt":"2026-09-11T00:12:21.696Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}