{"record":{"id":"95d9f939f355ec5a","repo":"MyCATApache/Mycat-Server","slug":"can-t-find-any-valid-datanode-tableconfig-getna","errorCode":null,"errorMessage":"can't find any valid datanode :${tableConfig.getName()} -> ${tableConfig.getPartitionColumn()} -> ${pair.colValue}","messagePattern":"can't find any valid datanode :(.+?) -> (.+?) -> (.+?)","errorType":"exception","errorClass":"java.sql.SQLNonTransientException","httpStatus":null,"severity":"error","filePath":"src/main/java/io/mycat/route/util/RouterUtil.java","lineNumber":1502,"sourceCode":"\t\r\n\tprivate static void setNodes(RouteResultset rrs, TableConfig tableConfig, String partionCol,\r\n        Set<String> tablesRouteSet, Map.Entry<String, Map<String, Set<ColumnRoutePair>>> entry1)\r\n        throws SQLNonTransientException {\r\n        Map<String, Set<ColumnRoutePair>> columnsMap = entry1.getValue();\r\n    \r\n        Set<ColumnRoutePair> partitionValue = columnsMap.get(partionCol);\r\n        if(partitionValue == null || partitionValue.size() == 0) {\r\n            tablesRouteSet.addAll(tableConfig.getDistTables());\r\n        } else {\r\n            for(ColumnRoutePair pair : partitionValue) {\r\n                AbstractPartitionAlgorithm algorithm = tableConfig.getRule().getRuleAlgorithm();\r\n                if(pair.colValue != null) {\r\n                    Integer tableIndex = algorithm.calculate(pair.colValue);\r\n                    if(tableIndex == null) {\r\n                        String msg = \"can't find any valid datanode :\" + tableConfig.getName()\r\n                                + \" -> \" + tableConfig.getPartitionColumn() + \" -> \" + pair.colValue;\r\n                        LOGGER.warn(msg);\r\n                        throw new SQLNonTransientException(msg);\r\n                    }\r\n                    String subTable = tableConfig.getDistTables().get(tableIndex);\r\n                    if(subTable != null) {\r\n                        tablesRouteSet.add(subTable);\r\n                        if(algorithm instanceof SlotFunction){\r\n                            rrs.getDataNodeSlotMap().put(subTable,((SlotFunction) algorithm).slotValue());\r\n                        }\r\n                    }\r\n                }\r\n                if(pair.rangeValue != null) {\r\n                    Integer[] tableIndexs = algorithm\r\n                            .calculateRange(pair.rangeValue.beginValue.toString(), pair.rangeValue.endValue.toString());\r\n                    for(Integer idx : tableIndexs) {\r\n                        String subTable = tableConfig.getDistTables().get(idx);\r\n                        if(subTable != null) {\r\n                            tablesRouteSet.add(subTable);\r\n                            if(algorithm instanceof SlotFunction){\r\n                                rrs.getDataNodeSlotMap().put(subTable,((SlotFunction) algorithm).slotValue());\r","sourceCodeStart":1484,"sourceCodeEnd":1520,"githubUrl":"https://github.com/MyCATApache/Mycat-Server/blob/65f8d8beb752f935752f2a0eec0ab017facab9ef/src/main/java/io/mycat/route/util/RouterUtil.java#L1484-L1520","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nInteger tableIndex = algorithm.calculate(pair.colValue); // null for '2026-13-01'\n// after: guard value format before routing\nif (pair.colValue == null || !pair.colValue.matches(\"\\\\d{8}\")) {\n    throw new SQLNonTransientException(\"invalid partition value: \" + pair.colValue);\n}\nInteger tableIndex = algorithm.calculate(pair.colValue);","handlingStrategy":"try-catch","validationCode":"Integer idx = algorithm.calculate(value);\nif (idx == null) throw new IllegalArgumentException(\"no dist sub-table for value: \" + value);","typeGuard":null,"tryCatchPattern":"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; }","preventionTips":["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"],"tags":["sharding","routing","partition"],"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"}