MyCATApache/Mycat-Server · error · ConfigException

only one rule can defined

Error message

only one rule can defined :${name}

What it means

Within one <tableRule> element, loadTableRules counts nested <rule> child elements. MyCat only supports a single rule (sharding column/algorithm pair) per tableRule, so more than one <rule> tag throws this ConfigException. The comment notes multi-column composite rules are planned but not implemented in this version.

Solutions

  1. Keep exactly one <rule> element per <tableRule> and restart.
  2. If multi-column sharding is needed, use an algorithm that itself handles composite keys (e.g. a custom AbstractPartitionAlgorithm fed one concatenated column or a complex sharding function) instead of multiple <rule> tags.
  3. Upgrade to a MyCat version that supports multi-column rules if the requirement is hard.

Example fix

// before (rule.xml)
<tableRule name="order-rule">
  <rule><columns>id</columns><algorithm>mod-long</algorithm></rule>
  <rule><columns>cust_id</columns><algorithm>hash-int</algorithm></rule>
</tableRule>
// after
<tableRule name="order-rule">
  <rule><columns>id</columns><algorithm>mod-long</algorithm></rule>
</tableRule>
Defensive patterns

Strategy: validation

Validate before calling

// Assert each tableRule has exactly one <rule> child before deployment
NodeList tableRules = doc.getElementsByTagName("tableRule");
for (int i = 0; i < tableRules.getLength(); i++) {
    Element tr = (Element) tableRules.item(i);
    if (tr.getElementsByTagName("rule").getLength() != 1)
        throw new IllegalStateException("tableRule " + tr.getAttribute("name") + " must define exactly one <rule>");
}

Try / catch

try {
    ruleLoader.load();
} catch (ConfigException e) {
    if (e.getMessage().startsWith("only one rule can defined")) {
        LOG.error("Multi-rule tableRule not supported: {}", e.getMessage());
    }
    throw e;
}

Prevention

When it happens

Trigger: A rule.xml tableRule block containing two or more <rule> children, e.g. trying to declare sharding on two columns; load() -> loadTableRules() sees ruleNodes.getLength() > 1.

Common situations: Developers attempting composite/multi-column sharding by adding a second <rule> entry; copy-pasted example configs from newer MyCat forks that support multiple rules; merged XML fragments.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at src/main/java/io/mycat/config/loader/xml/XMLRuleLoader.java:140

     */
	private void loadTableRules(Element root) throws SQLSyntaxErrorException {
		//获取每个tableRule标签
		NodeList list = root.getElementsByTagName("tableRule");
		for (int i = 0, n = list.getLength(); i < n; ++i) {
			Node node = list.item(i);
			if (node instanceof Element) {
				Element e = (Element) node;
				//先判断是否重复
				String name = e.getAttribute("name");
				if (tableRules.containsKey(name)) {
					throw new ConfigException("table rule " + name
							+ " duplicated!");
				}
				//获取rule标签
				NodeList ruleNodes = e.getElementsByTagName("rule");
				int length = ruleNodes.getLength();
				if (length > 1) {
					throw new ConfigException("only one rule can defined :"
							+ name);
				}
				//目前只处理第一个,未来可能有多列复合逻辑需求
				//RuleConfig是保存着rule与function对应关系的对象
				RuleConfig rule = loadRule((Element) ruleNodes.item(0));
				String funName = rule.getFunctionName();
				//判断function是否存在,获取function
				AbstractPartitionAlgorithm func = functions.get(funName);
				if (func == null) {
					throw new ConfigException("can't find function of name :"
							+ funName);
				}
				rule.setRuleAlgorithm(func);
				//保存到tableRules
				tableRules.put(name, new TableRuleConfig(name, rule));
			}
		}
	}

View on GitHub (pinned to 65f8d8beb7)