{"record":{"id":"2a4ac1c6d0ef6a0b","repo":"apache/shardingsphere","slug":"37","errorCode":"37","errorMessage":"Can not find actual data source intersection for logic tables '%s'.","messagePattern":"Can not find actual data source intersection for logic tables '(.+?)'\\.","errorType":"exception","errorClass":"DataSourceIntersectionNotFoundException","httpStatus":null,"severity":"error","filePath":"features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/route/engine/type/unicast/ShardingUnicastRouteEngine.java","lineNumber":108,"sourceCode":"    private void routeWithMultipleTables(final RouteContext routeContext, final ShardingRule shardingRule) {\n        List<RouteMapper> tableMappers = new ArrayList<>(logicTables.size());\n        Set<String> availableDataSourceNames = Collections.emptySet();\n        boolean first = true;\n        for (String each : logicTables) {\n            ShardingTable shardingTable = shardingRule.getShardingTable(each);\n            DataNode dataNode = shardingTable.getActualDataNodes().get(0);\n            tableMappers.add(new RouteMapper(each, dataNode.getTableName()));\n            Set<String> currentDataSourceNames = shardingTable.getActualDataNodes().stream().map(DataNode::getDataSourceName).collect(\n                    Collectors.toCollection(() -> new LinkedHashSet<>(shardingTable.getActualDataSourceNames().size(), 1F)));\n            if (first) {\n                availableDataSourceNames = currentDataSourceNames;\n                first = false;\n            } else {\n                availableDataSourceNames = Sets.intersection(availableDataSourceNames, currentDataSourceNames);\n            }\n        }\n        if (availableDataSourceNames.isEmpty()) {\n            throw new DataSourceIntersectionNotFoundException(logicTables);\n        }\n        String dataSourceName = getDataSourceName(availableDataSourceNames);\n        routeContext.getRouteUnits().add(new RouteUnit(new RouteMapper(dataSourceName, dataSourceName), tableMappers));\n    }\n    \n    private String getRandomDataSourceName(final Collection<String> dataSourceNames) {\n        Collection<String> usedDataSourceNames = connectionContext.getUsedDataSourceNames();\n        List<String> availableDataSourceNames = new ArrayList<>(usedDataSourceNames.isEmpty() ? dataSourceNames : usedDataSourceNames);\n        return availableDataSourceNames.get(ThreadLocalRandom.current().nextInt(availableDataSourceNames.size()));\n    }\n}\n","sourceCodeStart":90,"sourceCodeEnd":120,"githubUrl":"https://github.com/apache/shardingsphere/blob/e952770a215630a3659c75d64369168cd3e26b82/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/route/engine/type/unicast/ShardingUnicastRouteEngine.java#L90-L120","documentation":"DataSourceIntersectionNotFoundException is thrown by ShardingUnicastRouteEngine when a unicast statement (one that only needs any single data node, e.g. metadata queries/SHOW-like routing) references multiple sharded tables whose actual data source sets have no common data source. The engine intersects the data source names of each involved table's actualDataNodes and requires a non-empty intersection to pick one node; empty intersection means no single database contains all referenced tables.","triggerScenarios":"A statement routed unicast touching >=2 sharding tables where table A's actualDataNodes live only in ds_0/ds_1 and table B's only in ds_2/ds_3 — Sets.intersection across the per-table data source sets yields an empty set.","commonSituations":"Tables sharded to disjoint data source pools (per-tenant or per-region datasources); misconfigured actualDataNodes where one table's expressions omit a data source; growing a cluster by adding a new data source to some tables only.","solutions":["Ensure every sharded table referenced by the statement has at least one actual data node in a shared data source (overlap the actualDataNodes expressions).","If tables intentionally live in disjoint data sources, route the query to a federation/data-source solution or query the tables separately.","Fix actualDataNodes typos: verify with SHOW SHARDING TABLE RULES that each table's data sources are as intended."],"exampleFix":"# before: disjoint data sources\nt_order:      actualDataNodes: ds_${0..1}.t_order_${0..3}\nt_inventory:  actualDataNodes: ds_${2..3}.t_inventory\n\n# after: shared data source overlap\nt_order:      actualDataNodes: ds_${0..1}.t_order_${0..3}\nt_inventory:  actualDataNodes: ds_${0..1}.t_inventory","handlingStrategy":"validation","validationCode":"// For unicast-routed statements, assert a shared data source exists\nSet<String> dsOf(ShardingTable t) { return t.getActualDataNodes().stream().map(DataNode::getDataSourceName).collect(Collectors.toSet()); }\nSet<String> intersection = new HashSet<>(dsOf(tableA));\nintersection.retainAll(dsOf(tableB));\nif (intersection.isEmpty()) { throw new IllegalStateException(\"No common data source for unicast query\"); }","typeGuard":null,"tryCatchPattern":"try {\n    rs = stmt.executeQuery(sql);\n} catch (final DataSourceIntersectionNotFoundException ex) {\n    // split the statement per data source or fix rule overlap\n}","preventionTips":["Design table placement so tables used together share at least one data source.","When scaling out data sources, update all related sharding rules together."],"tags":["sharding","unicast-route","data-source","intersection","configuration"],"backgroundTag":null,"analyzedSha":"e952770a215630a3659c75d64369168cd3e26b82","analyzedAt":"2026-08-14T13:54:53.392Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}