{"record":{"id":"60ade7407d441370","repo":"MyCATApache/Mycat-Server","slug":"can-t-find-a-valid-data-node-for-specified-node-in","errorCode":null,"errorMessage":"Can't find a valid data node for specified node index :${tableConfig.getName()} -> ${tableConfig.getPartitionColumn()} -> ${pair.colValue} -> Index : ${nodeIndex}","messagePattern":"Can't find a valid data node for specified node index :(.+?) -> (.+?) -> (.+?) -> Index : (.+?)","errorType":"exception","errorClass":"java.sql.SQLNonTransientException","httpStatus":null,"severity":"error","filePath":"src/main/java/io/mycat/route/util/RouterUtil.java","lineNumber":1698,"sourceCode":"\t\t\t\t\t\t\t\tif(nodeIndex == null) {\r\n\t\t\t\t\t\t\t\t\tString msg = \"can't find any valid datanode :\" + tableConfig.getName()\r\n\t\t\t\t\t\t\t\t\t\t\t+ \" -> \" + tableConfig.getPartitionColumn() + \" -> \" + pair.colValue;\r\n\t\t\t\t\t\t\t\t\tLOGGER.warn(msg);\r\n\t\t\t\t\t\t\t\t\tthrow new SQLNonTransientException(msg);\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t\tArrayList<String> dataNodes = tableConfig.getDataNodes();\r\n\t\t\t\t\t\t\t\tString node;\r\n\t\t\t\t\t\t\t\tif (nodeIndex >=0 && nodeIndex < dataNodes.size()) {\r\n\t\t\t\t\t\t\t\t\tnode = dataNodes.get(nodeIndex);\r\n\r\n\t\t\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\t\t\tnode = null;\r\n\t\t\t\t\t\t\t\t\tString msg = \"Can't find a valid data node for specified node index :\"\r\n\t\t\t\t\t\t\t\t\t\t\t+ tableConfig.getName() + \" -> \" + tableConfig.getPartitionColumn()\r\n\t\t\t\t\t\t\t\t\t\t\t+ \" -> \" + pair.colValue + \" -> \" + \"Index : \" + nodeIndex;\r\n\t\t\t\t\t\t\t\t\tLOGGER.warn(msg);\r\n\t\t\t\t\t\t\t\t\tthrow new SQLNonTransientException(msg);\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\tif(node != null) {\r\n\t\t\t\t\t\t\t\t\tif(tablesRouteMap.get(tableName) == null) {\r\n\t\t\t\t\t\t\t\t\t\ttablesRouteMap.put(tableName, new HashSet<String>());\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\tif(algorithm instanceof SlotFunction){\r\n\t\t\t\t\t\t\t\t\t\trrs.getDataNodeSlotMap().put(node,((SlotFunction) algorithm).slotValue());\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\ttablesRouteMap.get(tableName).add(node);\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif(pair.rangeValue != null) {\r\n\t\t\t\t\t\t\t\tInteger[] nodeIndexs = algorithm\r\n\t\t\t\t\t\t\t\t\t\t.calculateRange(pair.rangeValue.beginValue.toString(), pair.rangeValue.endValue.toString());\r\n\t\t\t\t\t\t\t\tArrayList<String> dataNodes = tableConfig.getDataNodes();\r\n\t\t\t\t\t\t\t\tString node;\r\n\t\t\t\t\t\t\t\tfor(Integer idx : nodeIndexs) {\r\n\t\t\t\t\t\t\t\t\tif (idx >= 0 && idx < dataNodes.size()) {\r","sourceCodeStart":1680,"sourceCodeEnd":1716,"githubUrl":"https://github.com/MyCATApache/Mycat-Server/blob/65f8d8beb752f935752f2a0eec0ab017facab9ef/src/main/java/io/mycat/route/util/RouterUtil.java#L1680-L1716","documentation":"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.","triggerScenarios":"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().","commonSituations":"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.","solutions":["Add/restore dataNode entries in schema.xml so the count covers every index the rule can return, then reload config","Check the partition algorithm configuration (rule.xml / partition pattern file) and ensure its bucket count matches the number of dataNodes","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","For mod rules with negative/overflow hash results, upgrade or configure a hashing algorithm that returns non-negative indexes"],"exampleFix":"// before (rule returns 10, only 4 nodes)\nSELECT * FROM t_order WHERE user_id = 7; -- nodeIndex=10, dataNodes.size()=4 -> throws\n// after (schema.xml)\n<table name=\"t_order\" dataNode=\"dn1,dn2,dn3,dn4,dn5,dn6,dn7,dn8,dn9,dn10\" rule=\"mod-rule\" />","handlingStrategy":"validation","validationCode":"// Java: before issuing the query, check the rule's index is in range\nint idx = rule.calculate(columnValue);\nif (idx < 0 || idx >= tableConfig.getDataNodes().size()) {\n    throw new IllegalArgumentException(\"value \" + columnValue + \" maps to invalid node index \" + idx);\n}","typeGuard":null,"tryCatchPattern":"catch (SQLNonTransientException e) { log.error(\"route failed, check schema.xml dataNodes vs rule.xml\", e); throw new RouteConfigurationException(e.getMessage(), e); }","preventionTips":["Keep rule bucket count and dataNode count in sync; automate a config check that maxIndex < dataNodes.size()","After shrinking/expanding dataNodes, verify historical values still map to existing nodes","Use hashing algorithms that mask negative int results"],"tags":["sharding","routing","partition","datanode","config"],"backgroundTag":"value-out-of-range","analyzedSha":"65f8d8beb752f935752f2a0eec0ab017facab9ef","analyzedAt":"2026-09-11T00:12:21.696Z","contentChangedAt":"2026-09-11T00:12:21.696Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}