{"record":{"id":"a83a478b7b371ba3","repo":"MyCATApache/Mycat-Server","slug":"table-rule-name-duplicated","errorCode":null,"errorMessage":"table rule ${name} duplicated!","messagePattern":"table rule (.+?) duplicated!","errorType":"exception","errorClass":"ConfigException","httpStatus":null,"severity":"error","filePath":"src/main/java/io/mycat/config/loader/xml/XMLRuleLoader.java","lineNumber":133,"sourceCode":"\t *     <rule>\r\n\t *         <columns>create_date</columns>\r\n\t *         <algorithm>partbymonth</algorithm>\r\n\t *     </rule>\r\n\t * </tableRule>\r\n\t * @param root\r\n\t * @throws SQLSyntaxErrorException\r\n     */\r\n\tprivate void loadTableRules(Element root) throws SQLSyntaxErrorException {\r\n\t\t//获取每个tableRule标签\r\n\t\tNodeList list = root.getElementsByTagName(\"tableRule\");\r\n\t\tfor (int i = 0, n = list.getLength(); i < n; ++i) {\r\n\t\t\tNode node = list.item(i);\r\n\t\t\tif (node instanceof Element) {\r\n\t\t\t\tElement e = (Element) node;\r\n\t\t\t\t//先判断是否重复\r\n\t\t\t\tString name = e.getAttribute(\"name\");\r\n\t\t\t\tif (tableRules.containsKey(name)) {\r\n\t\t\t\t\tthrow new ConfigException(\"table rule \" + name\r\n\t\t\t\t\t\t\t+ \" duplicated!\");\r\n\t\t\t\t}\r\n\t\t\t\t//获取rule标签\r\n\t\t\t\tNodeList ruleNodes = e.getElementsByTagName(\"rule\");\r\n\t\t\t\tint length = ruleNodes.getLength();\r\n\t\t\t\tif (length > 1) {\r\n\t\t\t\t\tthrow new ConfigException(\"only one rule can defined :\"\r\n\t\t\t\t\t\t\t+ name);\r\n\t\t\t\t}\r\n\t\t\t\t//目前只处理第一个，未来可能有多列复合逻辑需求\r\n\t\t\t\t//RuleConfig是保存着rule与function对应关系的对象\r\n\t\t\t\tRuleConfig rule = loadRule((Element) ruleNodes.item(0));\r\n\t\t\t\tString funName = rule.getFunctionName();\r\n\t\t\t\t//判断function是否存在，获取function\r\n\t\t\t\tAbstractPartitionAlgorithm func = functions.get(funName);\r\n\t\t\t\tif (func == null) {\r\n\t\t\t\t\tthrow new ConfigException(\"can't find function of name :\"\r\n\t\t\t\t\t\t\t+ funName);\r","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/MyCATApache/Mycat-Server/blob/65f8d8beb752f935752f2a0eec0ab017facab9ef/src/main/java/io/mycat/config/loader/xml/XMLRuleLoader.java#L115-L151","documentation":"XMLRuleLoader.loadTableRules parses <tableRule> elements from rule.xml and stores them in a map keyed by the name attribute. If two tableRule elements share the same name, the second insertion is rejected with this ConfigException. The loader is fail-fast: duplicate rule names would make routing resolution ambiguous, so startup aborts.","triggerScenarios":"Starting MyCat with a rule.xml (or overlapping rule.xml files) that defines two <tableRule name=\"X\"> elements with the same name attribute; load() -> loadTableRules() hits tableRules.containsKey(name) on the second definition.","commonSituations":"Hand-editing rule.xml and copy-pasting a tableRule block without renaming it; merging config fragments from different environments; a hot-reload that appends a new rule without removing the old one.","solutions":["Open rule.xml and search for duplicate <tableRule name=\"...\"> entries; remove or rename the redundant one.","If two rules need similar config, give each a unique name and reference the correct one in each table's rule attribute.","After fixing, restart or reload MyCat config to confirm startup completes."],"exampleFix":"// before (rule.xml)\n<tableRule name=\"order-rule\">\n  <rule><columns>id</columns><algorithm>mod-long</algorithm></rule>\n</tableRule>\n<tableRule name=\"order-rule\">\n  <rule><columns>cust_id</columns><algorithm>hash-int</algorithm></rule>\n</tableRule>\n// after\n<tableRule name=\"order-rule\">\n  <rule><columns>id</columns><algorithm>mod-long</algorithm></rule>\n</tableRule>\n<tableRule name=\"order-cust-rule\">\n  <rule><columns>cust_id</columns><algorithm>hash-int</algorithm></rule>\n</tableRule>","handlingStrategy":"validation","validationCode":"// Before deploying rule.xml, fail fast on duplicate tableRule names\nSet<String> seen = new HashSet<>();\nNodeList rules = doc.getElementsByTagName(\"tableRule\");\nfor (int i = 0; i < rules.getLength(); i++) {\n    String name = ((Element) rules.item(i)).getAttribute(\"name\");\n    if (!seen.add(name)) throw new IllegalStateException(\"duplicate tableRule: \" + name);\n}","typeGuard":null,"tryCatchPattern":"try {\n    configLoader.load();\n} catch (ConfigException e) {\n    if (e.getMessage().contains(\"duplicated!\")) {\n        LOG.error(\"rule.xml has duplicate definitions: {}\", e.getMessage());\n        throw new ConfigValidationException(e);\n    }\n    throw e;\n}","preventionTips":["Keep one canonical rule.xml under version control; never hand-merge fragments.","Add a CI step (xmllint or a small script) that asserts unique tableRule names.","When adding a rule, search the file for the name first."],"tags":["configuration","xml","duplicate-key","startup"],"backgroundTag":"conflicting-config-options","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"}