MyCATApache/Mycat-Server · error · java.sql.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

Mycat throws this SQLNonTransientException during routing when a sharding rule maps a column value to a node index that does not correspond to any configured data node for the table. The partition algorithm returned nodeIndex, but dataNodes.get(nodeIndex) was out of range or invalid, so no route can be computed and the query cannot proceed. This is a fail-fast signal that the sharding data and the rule's node count disagree.

Solutions

  1. Add/restore dataNode entries in schema.xml so the count covers every index the rule can return, then reload config
  2. Check the partition algorithm configuration (rule.xml / partition pattern file) and ensure its bucket count matches the number of dataNodes
  3. Identify the offending value (it is printed in the message: table -> partitionColumn -> colValue) and verify how the rule maps it; fix bad data or rule params
  4. For mod rules with negative/overflow hash results, upgrade or configure a hashing algorithm that returns non-negative indexes

Example fix

// before (rule returns 10, only 4 nodes)
SELECT * FROM t_order WHERE user_id = 7; -- nodeIndex=10, dataNodes.size()=4 -> throws
// after (schema.xml)
<table name="t_order" dataNode="dn1,dn2,dn3,dn4,dn5,dn6,dn7,dn8,dn9,dn10" rule="mod-rule" />
Defensive patterns

Strategy: validation

Validate before calling

// Java: before issuing the query, check the rule's index is in range
int idx = rule.calculate(columnValue);
if (idx < 0 || idx >= tableConfig.getDataNodes().size()) {
    throw new IllegalArgumentException("value " + columnValue + " maps to invalid node index " + idx);
}

Try / catch

catch (SQLNonTransientException e) { log.error("route failed, check schema.xml dataNodes vs rule.xml", e); throw new RouteConfigurationException(e.getMessage(), e); }

Prevention

When it happens

Trigger: A SELECT/UPDATE with an equals condition on the partition column is routed via RouterUtil.tableRouteResultForSingleColumnRule (public RouterUtil entry); the rule algorithm (e.g. PartitionByMod, partitionDate) computes an index that is < 0 or >= tableConfig.getDataNodes().size().

Common situations: schema.xml dataNode list for the table was reduced after rows were written under a larger count (e.g. shrinking a mod-10 table to 4 nodes); a hash/date function whose max index exceeds the node list; String/hash overflow producing negative index; partition function config (partition-rules xml) referencing more nodes than exist.

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/60ade7407d441370. Report an issue: GitHub.

Appendix: source

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

								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) {
									if (idx >= 0 && idx < dataNodes.size()) {

View on GitHub (pinned to 65f8d8beb7)