apache/shardingsphere · error · ShardingDDLRouteException
40
40
Error message
'DROP INDEX' can not route correctly for INDEX '%s'.
What it means
Thrown by ShardingDropIndexRouteChecker when a DROP INDEX statement on a sharding (or binding) table produces route units whose table data-node counts differ. ShardingSphere cannot rewrite a DROP INDEX consistently across databases when the target index's logic table does not resolve to the same number of actual tables in every routed data source, so it fails fast instead of dropping only a subset of the index. The index name is resolved to a logic table by scanning every schema table for one that contains the index.
Source
Thrown at features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/route/engine/checker/ddl/ShardingDropIndexRouteContextChecker.java:63
DropIndexStatement dropIndexStatement = (DropIndexStatement) queryContext.getSqlStatementContext().getSqlStatement();
Collection<IndexSegment> indexSegments = dropIndexStatement.getIndexes();
Optional<String> logicTableName = dropIndexStatement.getSimpleTable().map(optional -> optional.getTableName().getIdentifier().getValue());
if (logicTableName.isPresent()) {
validateDropIndexRouteUnit(shardingRule, routeContext, indexSegments, logicTableName.get());
} else {
String defaultSchemaName = new DatabaseTypeRegistry(queryContext.getSqlStatementContext().getSqlStatement().getDatabaseType()).getDefaultSchemaName(database.getName());
for (IndexSegment each : indexSegments) {
ShardingSphereSchema schema = each.getOwner().map(optional -> optional.getIdentifier().getValue()).map(database::getSchema).orElseGet(() -> database.getSchema(defaultSchemaName));
logicTableName = schema.getAllTables().stream().filter(table -> table.containsIndex(each.getIndexName().getIdentifier().getValue())).findFirst().map(ShardingSphereTable::getName);
logicTableName.ifPresent(optional -> validateDropIndexRouteUnit(shardingRule, routeContext, indexSegments, optional));
}
}
}
private void validateDropIndexRouteUnit(final ShardingRule shardingRule, final RouteContext routeContext, final Collection<IndexSegment> indexSegments, final String logicTableName) {
if (ShardingSupportedCheckUtils.isRouteUnitDataNodeDifferentSize(shardingRule, routeContext, logicTableName)) {
Collection<String> indexNames = indexSegments.stream().map(each -> each.getIndexName().getIdentifier().getValue()).collect(Collectors.toList());
throw new ShardingDDLRouteException("DROP", "INDEX", indexNames);
}
}
}
View on GitHub (pinned to e952770a21)
Solutions
- Make the actual data nodes of the owning sharding table symmetric across all routed data sources (same table count per data source) in the sharding rule, then re-run DROP INDEX.
- Verify which logic table owns the index (every schema table is scanned via containsIndex) and check its actualDataNodes configuration for asymmetry.
- If the topology is intentionally asymmetric, drop the index directly on each physical database, bypassing ShardingSphere routing.
- Check binding table groups: a binding table whose members have different topologies also triggers this path.
Example fix
# before (asymmetric topology triggers error)
tables:
- logicTable: t_order
actualDataNodes: ds_0.t_order_0..3
- logicTable: t_order_item
actualDataNodes: ds_0.t_order_item_0..1,ds_1.t_order_item_0..1
# after (symmetric per data source)
tables:
- logicTable: t_order
actualDataNodes: ds_${0..1}.t_order_${0..3}
- logicTable: t_order_item
actualDataNodes: ds_${0..1}.t_order_item_${0..3} Defensive patterns
Strategy: validation
Validate before calling
// Before issuing DROP INDEX, assert every route unit has the same table count per data source
ShardingTable table = database.getSchema(schemaName).getTable("t_order");
Map<String, Long> perDs = table.getIndexTableDataNodes() == null ? null : null; // conceptual
// practical: inspect the sharding rule's actual data nodes per data source
Map<String, Integer> counts = new HashMap<>();
for (DataNode dn : shardingTable.getActualDataNodes()) {
counts.merge(dn.getDataSourceName(), 1, Integer::sum);
}
boolean symmetric = new HashSet<>(counts.values()).size() <= 1;
if (!symmetric) { /* align topology or execute DROP INDEX per physical DB */ } Try / catch
try {
statement.execute("DROP INDEX idx_order_no ON t_order");
} catch (final ShardingSphereException ex) {
if (ex.getMessage().contains("'DROP INDEX' can not route correctly")) {
// fall back: drop the index on each physical data source directly
} else { throw ex; }
} Prevention
- Keep actual data nodes symmetric across data sources for every sharded and binding table.
- Run SHOW SHARDING TABLE RULES after topology changes and verify per-data-source table counts match.
- Prefer defining indexes through ShardingSphere-routed DDL so metadata and rules stay consistent.
When it happens
Trigger: Executing DROP INDEX where the resolved logic table (the table whose metadata contains indexNames) routes to route units with different numbers of table mappers (ShardingSupportedCheckUtils.isRouteUnitDataNodeDifferentSize returns true). Typical with uneven actual-data-nodes per data source for the sharding table, or when the index belongs to a table in a binding group with mismatched topology.
Common situations: A sharding table configured with different actual table counts per data source (e.g. ds_0 has 4 tables, ds_1 has 2) and a DROP INDEX issued through Proxy/JDBC; or an index created directly on one physical table so metadata resolution picks a table whose routing is asymmetric across data sources.
Related errors
AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14).
Data as JSON: /api/errors/029641a09095d2a2.
Report an issue: GitHub.