MyCATApache/Mycat-Server · error · java.sql.SQLNonTransientException
can't find any valid datanode
Error message
can't find any valid datanode :${tableConfig.getName()} -> ${tableConfig.getPartitionColumn()} -> ${pair.colValue} What it means
Thrown during dist-table routing when the sharding algorithm's calculate(colValue) returns null for a partition-column value, meaning no sub-table index maps to that value. Mycat cannot determine which dist sub-table holds the row.
Solutions
- Extend the rule mapping in rule.xml to cover the offending value or add a default mapping
- Fix the client to send partition-column values in the format the algorithm expects (e.g. 'YYYYMMDD' for date rules)
- Test the partition function standalone with the failing value to confirm calculate() behavior
- Reject or sanitize such values at the application layer before queries
Example fix
// before
Integer tableIndex = algorithm.calculate(pair.colValue); // null for '2026-13-01'
// after: guard value format before routing
if (pair.colValue == null || !pair.colValue.matches("\\d{8}")) {
throw new SQLNonTransientException("invalid partition value: " + pair.colValue);
}
Integer tableIndex = algorithm.calculate(pair.colValue); Defensive patterns
Strategy: try-catch
Validate before calling
Integer idx = algorithm.calculate(value);
if (idx == null) throw new IllegalArgumentException("no dist sub-table for value: " + value); Try / catch
try { rrs = route(...); } catch (SQLNonTransientException e) { if (e.getMessage().startsWith("can't find any valid datanode")) { LOG.warn("partition value unmapped, check rule.xml: " + e.getMessage()); } throw e; } Prevention
- Cover the full value domain in the sharding function (ranges + default)
- Validate partition value formats at the application boundary
- Unit-test the algorithm against all real key values
When it happens
Trigger: A condition or insert value on the table's partition column is passed to algorithm.calculate() and returns null (value outside configured ranges, wrong format, e.g. non-numeric string for a numeric rule).
Common situations: Dist table rules in rule.xml with ranges that don't cover all values; date strings in an unexpected format; null/unparseable partition values in WHERE clauses.
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 a valid data node for specified node index
- Can't find valid data node(s) for some of specified node…
- columnValue: Please eliminate any quote and non number…
- columnValue: Please check if the format satisfied.
- can't find any valid datanode : -> ->
AI-assisted analysis of MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11).
Data as JSON: /api/errors/95d9f939f355ec5a.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/io/mycat/route/util/RouterUtil.java:1502
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){
rrs.getDataNodeSlotMap().put(subTable,((SlotFunction) algorithm).slotValue());
View on GitHub (pinned to 65f8d8beb7)