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
- 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
- Fix the custom partition algorithm so returned indexes are 0-based and within [0, nodeCount)
- 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
- Keep rule function count exactly equal to the table's dataNode count
- CI-lint rule.xml against schema.xml on every config change
- Ensure custom AbstractPartitionAlgorithm implementations return 0-based indexes within range
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
- can't find any valid datanode : -> ->
- find no Route:
- can't find any valid datanode : + tableConfig.getName() + …
- crc32slot_ .properties does not match schema table dataNode.
- schema: ,table: ,sql: is not allowed,because table is…
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)