{"record":{"id":"0552d4f77f2f2d2a","repo":"MyCATApache/Mycat-Server","slug":"invalid-route-in-sql-multi-tables-found-but-datan-0552d4","errorCode":null,"errorMessage":"invalid route in sql, multi tables found but datanode has no intersection  sql:\" + ctx.getSql()","messagePattern":"invalid route in sql, multi tables found but datanode has no intersection  sql:\" \\+ ctx\\.getSql\\(\\)","errorType":"exception","errorClass":"SQLNonTransientException","httpStatus":null,"severity":"error","filePath":"src/main/java/io/mycat/route/util/RouterUtil.java","lineNumber":1324,"sourceCode":"\t\t}\r\n\r\n\r\n\t\tboolean isFirstAdd = true;\r\n\t\tfor(Map.Entry<String, Set<String>> entry : tablesRouteMap.entrySet()) {\r\n\t\t\tif(entry.getValue() == null || entry.getValue().size() == 0) {\r\n\t\t\t\tthrow new SQLNonTransientException(\"parent key can't find any valid datanode \");\r\n\t\t\t} else {\r\n\t\t\t\tif(isFirstAdd) {\r\n\t\t\t\t\tretNodesSet.addAll(entry.getValue());\r\n\t\t\t\t\tisFirstAdd = false;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tretNodesSet.retainAll(entry.getValue());\r\n\t\t\t\t\tif(retNodesSet.size() == 0) {//两个表的路由无交集\r\n\t\t\t\t\t\tString errMsg = \"invalid route in sql, multi tables found but datanode has no intersection \"\r\n\t\t\t\t\t\t\t\t+ \" sql:\" + ctx.getSql();\r\n\t\t\t\t\t\tLOGGER.warn(errMsg);\r\n\t\t\t\t\t\tthrow new SQLNonTransientException(errMsg);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif(retNodesSet != null && retNodesSet.size() > 0) {\r\n\t\t\tString tableName = tables.get(0);\r\n\t\t\tTableConfig tableConfig = schema.getTables().get(tableName.toUpperCase());\r\n\t\t\tif(tableConfig.isDistTable()){\r\n\t\t\t    routeToDistTableNode(schema, rrs, ctx.getSql(), tablesAndConditions, cachePool, isSelect, null);\r\n\t\t\t\treturn rrs;\r\n\t\t\t}\r\n\r\n\t\t\tif(retNodesSet.size() > 1 && isAllGlobalTable(ctx, schema)) {\r\n\t\t\t\t// mulit routes ,not cache route result\r\n\t\t\t\tif (isSelect) {\r\n\t\t\t\t\trrs.setCacheAble(false);\r\n\t\t\t\t\tArrayList<String> retNodeList = new ArrayList<String>(retNodesSet);\r\n\t\t\t\t\tCollections.shuffle(retNodeList);//by kaiz : add shuffle\r","sourceCodeStart":1306,"sourceCodeEnd":1342,"githubUrl":"https://github.com/MyCATApache/Mycat-Server/blob/65f8d8beb752f935752f2a0eec0ab017facab9ef/src/main/java/io/mycat/route/util/RouterUtil.java#L1306-L1342","documentation":"Thrown by RouterUtil when routing a SQL statement that touches multiple sharded tables: each table's sharding key resolves to a set of datanodes, and the code intersects the sets (retailAll). When the intersection is empty, no single datanode can serve all tables and the route is impossible, so a SQLNonTransientException is thrown with the original SQL attached. This fires for cross-shard joins/lookups whose sharding values point at disjoint nodes; it is deterministic (non-transient) — the SQL or data distribution must change, not be retried.","triggerScenarios":"Thrown at src/main/java/io/mycat/route/util/RouterUtil.java:1324 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Rewrite the SQL so the joined/related tables route to at least one common datanode, e.g. use the sharding column values of the child-table constraint in the WHERE clause so each table's route set overlaps","Check that the sharding columns used in the SQL actually restrict routes on all involved tables; add equality predicates on sharding keys for tables whose route set is unconstrained (null/empty routes also throw)","If the query legitimately spans unrelated shards, split it into multiple statements per shard or use a global table / different sharding strategy so routes intersect"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"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"}