MyCATApache/Mycat-Server · error · SQLNonTransientException

Can't find a valid data node for specified node index : +…

Error message

Can't find a valid data node for specified node index : + tableConfig.getName() +  ->  + tableConfig.getPartitionColumn() +  ->  + pair.colValue +  ->  + Index :  + nodeIndex

What it means

After the algorithm computes a node index for a partition-column value, RouterUtil validates nodeIndex against the table's dataNodes list (0 <= index < size). An out-of-bounds index means the sharding function returned an index with no configured data node, and it throws SQLNonTransientException including the index value.

Solutions

  1. Align rule.xml function count/ranges with the table's dataNode count in schema.xml (e.g. count equals number of dataNodes) and reload both
  2. Fix the custom partition algorithm so returned indexes are 0-based and within [0, nodeCount)
  3. Add the missing dataNode(s) referenced by the rule to the table config

Example fix

// before (rule.xml) count=10 but only 4 dataNodes
<property name="count">10</property>
// after
<property name="count">4</property>
Defensive patterns

Strategy: validation

Validate before calling

// check rule count matches dataNode count before deploy
int count = ruleFunctionCount("mod-rule");      // from rule.xml
int nodes = tableDataNodeCount("orders");      // from schema.xml
if (count != nodes) throw new IllegalStateException("Rule count " + count + " != dataNode count " + nodes);

Try / catch

try {
    execute(query);
} catch (SQLNonTransientException e) {
    if (e.getMessage().contains("for specified node index"))
        throw new IllegalStateException("rule.xml count out of sync with schema.xml dataNodes", e);
    throw e;
}

Prevention

When it happens

Trigger: algorithm.calculate() returns an index >= dataNodes.size() (or negative) — e.g. a hash/mod rule configured with count larger than the number of dataNodes on the table.

Common situations: Rule function count increased or table dataNodes reduced without keeping them in sync; custom algorithm returning 1-based indexes or bad values; schema.xml edited to remove nodes while rule.xml still maps to them.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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

Appendix: source

Thrown at src/main/java/io/mycat/route/util/RouterUtil.java:1697

								Integer nodeIndex = algorithm.calculate(StringUtil.removeBackquote(pair.colValue));
								if(nodeIndex == null) {
									String msg = "can't find any valid datanode :" + tableConfig.getName()
											+ " -> " + tableConfig.getPartitionColumn() + " -> " + pair.colValue;
									LOGGER.warn(msg);
									throw new SQLNonTransientException(msg);
								}

								ArrayList<String> dataNodes = tableConfig.getDataNodes();
								String node;
								if (nodeIndex >=0 && nodeIndex < dataNodes.size()) {
									node = dataNodes.get(nodeIndex);

								} else {
									node = null;
									String msg = "Can't find a valid data node for specified node index :"
											+ tableConfig.getName() + " -> " + tableConfig.getPartitionColumn()
											+ " -> " + pair.colValue + " -> " + "Index : " + nodeIndex;
									LOGGER.warn(msg);
									throw new SQLNonTransientException(msg);
								}
								if(node != null) {
									if(tablesRouteMap.get(tableName) == null) {
										tablesRouteMap.put(tableName, new HashSet<String>());
									}
									if(algorithm instanceof SlotFunction){
										rrs.getDataNodeSlotMap().put(node,((SlotFunction) algorithm).slotValue());
									}
									tablesRouteMap.get(tableName).add(node);
								}
							}
							if(pair.rangeValue != null) {
								Integer[] nodeIndexs = algorithm
										.calculateRange(pair.rangeValue.beginValue.toString(), pair.rangeValue.endValue.toString());
								ArrayList<String> dataNodes = tableConfig.getDataNodes();
								String node;
								for(Integer idx : nodeIndexs) {

View on GitHub (pinned to 65f8d8beb7)