MyCATApache/Mycat-Server · error · SQLNonTransientException
can't find any valid datanode : + tableConfig.getName() + …
Error message
can't find any valid datanode : + tableConfig.getName() + -> + tableConfig.getPartitionColumn() + -> + pair.colValue
What it means
While routing a district (dist) table, RouterUtil feeds each condition value of the partition column into the rule's AbstractPartitionAlgorithm.calculate(). A null return means the sharding algorithm cannot map the value to any table index, so it throws SQLNonTransientException naming table, partition column, and the offending value.
Solutions
- Fix the data value or add a partition rule branch covering that value's range/type
- Adjust the partition algorithm configuration (count/mapFile) to cover the full value domain and reload
- Clean or transform invalid partition-column values before they reach MyCat
- Add a default route in the rule so unmapped values fall to a designated node
Example fix
// before
algorithm.calculate("abc") -> null // mod-long rule on a varchar column
// after (rule.xml)
<function name="hash-string" class="io.mycat.route.function.PartitionByString">
<property name="count">3</property>
</function> // or cast the column value before querying Defensive patterns
Strategy: validation
Validate before calling
// pre-check that partition values are mappable (example: mod-long)
Object v = row.get(partitionColumn);
if (v == null || !(v instanceof Number))
throw new IllegalArgumentException("Partition column " + partitionColumn + " must be a non-null number for this rule: " + v); Try / catch
try {
execute(shardedQuery);
} catch (SQLNonTransientException e) {
if (e.getMessage().startsWith("can't find any valid datanode")) {
log.warn("Unroutable partition value: " + e.getMessage());
// route to a direct data-node connection or quarantine the value
} else throw e;
} Prevention
- Validate partition-column values (type/range) at application boundary before queries
- Cover the full value domain in rule.xml (ranges, count, mapFile)
- Add tests exercising min/max/typical partition values against the algorithm
When it happens
Trigger: Executing a query/insert on a dist table where a WHERE/JOIN condition value for the partition column falls outside the algorithm's valid domain (e.g. string fed to a numeric hash, value outside enumerated range).
Common situations: Partition function (e.g. PartitionByString/mod-long) cannot handle the value type or range; data contains legacy/garbage values not covered by the partition map; column values changed after the rule was configured; NULL-adjacent sentinel values.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- can't find any valid datanode : -> ->
- find no Route:
- Can't find a valid data node for specified node index : +…
- schema: ,table: ,sql: is not allowed,because table is…
- can't find hint datanode
AI-assisted analysis of MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11).
Data as JSON: /api/errors/31c7caeb789deb4a.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/io/mycat/route/util/RouterUtil.java:1501
}
private static void setNodes(RouteResultset rrs, TableConfig tableConfig, String partionCol,
Set<String> tablesRouteSet, Map.Entry<String, Map<String, Set<ColumnRoutePair>>> entry1)
throws SQLNonTransientException {
Map<String, Set<ColumnRoutePair>> columnsMap = entry1.getValue();
Set<ColumnRoutePair> partitionValue = columnsMap.get(partionCol);
if(partitionValue == null || partitionValue.size() == 0) {
tablesRouteSet.addAll(tableConfig.getDistTables());
} else {
for(ColumnRoutePair pair : partitionValue) {
AbstractPartitionAlgorithm algorithm = tableConfig.getRule().getRuleAlgorithm();
if(pair.colValue != null) {
Integer tableIndex = algorithm.calculate(pair.colValue);
if(tableIndex == null) {
String msg = "can't find any valid datanode :" + tableConfig.getName()
+ " -> " + tableConfig.getPartitionColumn() + " -> " + pair.colValue;
LOGGER.warn(msg);
throw new SQLNonTransientException(msg);
}
String subTable = tableConfig.getDistTables().get(tableIndex);
if(subTable != null) {
tablesRouteSet.add(subTable);
if(algorithm instanceof SlotFunction){
rrs.getDataNodeSlotMap().put(subTable,((SlotFunction) algorithm).slotValue());
}
}
}
if(pair.rangeValue != null) {
Integer[] tableIndexs = algorithm
.calculateRange(pair.rangeValue.beginValue.toString(), pair.rangeValue.endValue.toString());
for(Integer idx : tableIndexs) {
String subTable = tableConfig.getDistTables().get(idx);
if(subTable != null) {
tablesRouteSet.add(subTable);
if(algorithm instanceof SlotFunction){
View on GitHub (pinned to 65f8d8beb7)