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

  1. Fix the data value or add a partition rule branch covering that value's range/type
  2. Adjust the partition algorithm configuration (count/mapFile) to cover the full value domain and reload
  3. Clean or transform invalid partition-column values before they reach MyCat
  4. 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

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


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)