MyCATApache/Mycat-Server · error · java.lang.IllegalArgumentException
route rule for table
Error message
route rule for table ${tc.getName()} is required: ${ctx.getSql()} What it means
Thrown when a DML (typically INSERT) targets a sharded table but the SQL contains no condition/value usable by the required route rule — checkRuleRequired() fails. The table's rule-required flag demands routing input that the statement does not provide.
Solutions
- Always include the partition column with a valid value in INSERT statements
- Set ruleRequired="false" in schema.xml if routing without a rule value is acceptable (row goes to default node semantics)
- Add the partition column to the application's insert code/ORM mapping
- Use a childTable/ER config if inserts belong to a parent's shard
Example fix
-- before INSERT INTO orders(order_id, amount) VALUES(1001, 50); -- after (include partition column 'customer_id') INSERT INTO orders(order_id, customer_id, amount) VALUES(1001, 5, 50);
Defensive patterns
Strategy: validation
Validate before calling
// Ensure the partition column is present in INSERT column list before sending
if (!insertColumns.contains(tc.getPartitionColumn())) throw new IllegalArgumentException("shard key required: " + tc.getPartitionColumn()); Try / catch
try { rrs = route(...); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith("route rule for table")) { LOG.warn("missing partition column in statement", e); } throw e; } Prevention
- Always include the shard key in INSERT statements
- Keep ruleRequired=true to catch shard-key omissions early rather than mis-routing
- Add ORM-level validation requiring the partition column on inserts
When it happens
Trigger: INSERT into a sharded table where ruleRequired=true and the statement omits the partition column, or the partition column value cannot be extracted for routing.
Common situations: INSERT statements that don't list the partition column; schema.xml sets ruleRequired="true" but applications insert rows without the shard key; batch inserts missing the column in some rows.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- partition table, insert must provide ColumnList
- bad insert sql columnSize != valueSize:values:
- can't find any valid datanode : -> ->
- find no Route:
- invalid sql
AI-assisted analysis of MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11).
Data as JSON: /api/errors/bf4500fd5d6659be.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/io/mycat/route/util/RouterUtil.java:1395
Map<String, Map<String, Set<ColumnRoutePair>>> tablesAndConditions = routeUnit.getTablesAndConditions();
if(tc.isDistTable()){
Set<String> keySet = tablesAndConditions.keySet();
//Map.Entry<String, Map<String, Set<ColumnRoutePair>>> entry = (Entry<String, Map<String, Set<ColumnRoutePair>>>) tablesAndConditions.get(keySet.toArray()[0]);
return routeToDistTableNode(schema,rrs,ctx.getSql(), tablesAndConditions, cachePool,isSelect, null);
}
if(tc.isGlobalTable()) {//全局表
if(isSelect) {
// global select ,not cache route result
rrs.setCacheAble(false);
return routeToSingleNode(rrs, getAliveRandomDataNode(tc)/*getRandomDataNode(tc)*/, ctx.getSql());
} else {//insert into 全局表的记录
return routeToMultiNode(false, rrs, tc.getDataNodes(), ctx.getSql(),true);
}
} else {//单表或者分库表
if (!checkRuleRequired(schema, ctx, routeUnit, tc)) {
throw new IllegalArgumentException("route rule for table "
+ tc.getName() + " is required: " + ctx.getSql());
}
if(tc.getPartitionColumn() == null && !tc.isSecondLevel()) {//单表且不是childTable
// return RouterUtil.routeToSingleNode(rrs, tc.getDataNodes().get(0),ctx.getSql());
return routeToMultiNode(rrs.isCacheAble(), rrs, tc.getDataNodes(), ctx.getSql());
} else {
//每个表对应的路由映射
Map<String,Set<String>> tablesRouteMap = new HashMap<String,Set<String>>();
if(routeUnit.getTablesAndConditions() != null && routeUnit.getTablesAndConditions().size() > 0) {
RouterUtil.findRouteWithcConditionsForTables(schema, rrs, routeUnit.getTablesAndConditions(), tablesRouteMap, ctx.getSql(), cachePool, isSelect);
if(rrs.isFinishedRoute()) {
return rrs;
}
}
if(tablesRouteMap.get(tableName) == null) {
return routeToMultiNode(rrs.isCacheAble(), rrs, tc.getDataNodes(), ctx.getSql());
View on GitHub (pinned to 65f8d8beb7)