{"record":{"id":"52aea27684d24a52","repo":"MyCATApache/Mycat-Server","slug":"parent-key-can-t-find-valid-datanode-expect-1-bu","errorCode":null,"errorMessage":"parent key can't find  valid datanode ,expect 1 but found: {size}","messagePattern":"parent key can't find  valid datanode ,expect 1 but found: (.+?)","errorType":"exception","errorClass":"SQLNonTransientException","httpStatus":null,"severity":"error","filePath":"src/main/java/io/mycat/route/util/RouterUtil.java","lineNumber":1096,"sourceCode":"\t\t\tRouteResultset rrs, TableConfig tc, String joinKeyVal)\r\n\t\t\tthrows SQLNonTransientException {\r\n\r\n\t\t// only has one parent level and ER parent key is parent\r\n\t\t// table's partition key\r\n\t\tif (tc.isSecondLevel()\r\n\t\t\t\t//判断是否为二级子表（父表不再有父表）\r\n\t\t\t\t&& tc.getParentTC().getPartitionColumn()\r\n\t\t\t\t.equals(tc.getParentKey())) { // using\r\n\t\t\t// parent\r\n\t\t\t// rule to\r\n\t\t\t// find\r\n\t\t\t// datanode\r\n\t\t\tSet<ColumnRoutePair> parentColVal = new HashSet<ColumnRoutePair>(1);\r\n\t\t\tColumnRoutePair pair = new ColumnRoutePair(joinKeyVal);\r\n\t\t\tparentColVal.add(pair);\r\n\t\t\tSet<String> dataNodeSet = ruleCalculate(tc.getParentTC(), parentColVal,rrs.getDataNodeSlotMap());\r\n\t\t\tif (dataNodeSet.isEmpty() || dataNodeSet.size() > 1) {\r\n\t\t\t\tthrow new SQLNonTransientException(\r\n\t\t\t\t\t\t\"parent key can't find  valid datanode ,expect 1 but found: \"\r\n\t\t\t\t\t\t\t\t+ dataNodeSet.size());\r\n\t\t\t}\r\n\t\t\tString dn = dataNodeSet.iterator().next();\r\n\t\t\tif (LOGGER.isDebugEnabled()) {\r\n\t\t\t\tLOGGER.debug(\"found partion node (using parent partion rule directly) for child table to insert  \"\r\n\t\t\t\t\t\t+ dn + \" sql :\" + stmt);\r\n\t\t\t}\r\n\t\t\treturn RouterUtil.routeToSingleNode(rrs, dn, stmt);\r\n\t\t}\r\n\t\treturn null;\r\n\t}\r\n\r\n\t/**\r\n\t * @return dataNodeIndex -&gt; [partitionKeysValueTuple+]\r\n\t */\r\n\tpublic static Set<String> ruleByJoinValueCalculate(RouteResultset rrs, TableConfig tc,\r\n\t\t\tSet<ColumnRoutePair> colRoutePairSet) throws SQLNonTransientException {\r","sourceCodeStart":1078,"sourceCodeEnd":1114,"githubUrl":"https://github.com/MyCATApache/Mycat-Server/blob/65f8d8beb752f935752f2a0eec0ab017facab9ef/src/main/java/io/mycat/route/util/RouterUtil.java#L1078-L1114","documentation":"When inserting into an ER/child table, MyCat computes the target data node by applying the parent table's sharding rule to the join key value. If ruleCalculate returns zero nodes or more than one node, the child row cannot be deterministically placed, so SQLNonTransientException('parent key can't find valid datanode, expect 1 but found: N') is thrown.","triggerScenarios":"INSERT into a child (ER) table where the parent key value, run through the parent table's rule algorithm, maps to no datanode or to multiple datanodes (e.g. parent uses a rule that fans out, or the join key value is out of the algorithm's range returning null/empty).","commonSituations":"Child table's <childTable> joinKey values not covered by the parent's sharding algorithm; parent table configured with a multi-node rule (e.g. a range rule matching multiple nodes); inserting child rows before any parent row exists.","solutions":["Ensure the parent key value in the child insert maps to exactly one datanode under the parent's rule (check algorithm calculate() for that value)","Insert the parent row first and use a joinKey value consistent with it","Use a single-node-exact rule (e.g. mod/hash) on the parent table so child routing resolves to one node"],"exampleFix":"-- before: parent rule returns null for user_id=9999\nINSERT INTO t_order_item (id, order_id, user_id) VALUES (1, 10, 9999);\n-- after: use a parent-key value covered by the rule\nINSERT INTO t_order_item (id, order_id, user_id) VALUES (1, 10, 100);","handlingStrategy":"validation","validationCode":"// before child-table insert\nSet<String> dns = ruleCalculate(parentTC, colPairs, slotMap);\nif (dns.size() != 1) throw new IllegalArgumentException(\"parent key maps to \" + dns.size() + \" datanodes, need exactly 1\");","typeGuard":null,"tryCatchPattern":"try { insertChild(row); } catch (SQLNonTransientException e) { if (e.getMessage().contains(\"parent key can't find\")) { /* insert parent first or fix key value */ } throw e; }","preventionTips":["Insert parent rows before child rows","Use single-node-exact rules (mod/hash) for ER parents","Validate join-key values against the parent algorithm range"],"tags":["sharding","er-table","insert"],"backgroundTag":"invalid-argument-value","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"}