{"record":{"id":"bf4500fd5d6659be","repo":"MyCATApache/Mycat-Server","slug":"route-rule-for-table-tc-getname-is-required","errorCode":null,"errorMessage":"route rule for table ${tc.getName()} is required: ${ctx.getSql()}","messagePattern":"route rule for table (.+?) is required: (.+?)","errorType":"exception","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/main/java/io/mycat/route/util/RouterUtil.java","lineNumber":1395,"sourceCode":"\r\n\t\tMap<String, Map<String, Set<ColumnRoutePair>>> tablesAndConditions = routeUnit.getTablesAndConditions();\r\n        if(tc.isDistTable()){\r\n            Set<String> keySet = tablesAndConditions.keySet();\r\n            //Map.Entry<String, Map<String, Set<ColumnRoutePair>>> entry = (Entry<String, Map<String, Set<ColumnRoutePair>>>) tablesAndConditions.get(keySet.toArray()[0]);\r\n            return routeToDistTableNode(schema,rrs,ctx.getSql(), tablesAndConditions, cachePool,isSelect, null);\r\n        }\r\n\r\n\t\tif(tc.isGlobalTable()) {//全局表\r\n\t\t\tif(isSelect) {\r\n\t\t\t\t// global select ,not cache route result\r\n\t\t\t\trrs.setCacheAble(false);\r\n\t\t\t\treturn routeToSingleNode(rrs, getAliveRandomDataNode(tc)/*getRandomDataNode(tc)*/, ctx.getSql());\r\n\t\t\t} else {//insert into 全局表的记录\r\n\t\t\t\treturn routeToMultiNode(false, rrs, tc.getDataNodes(), ctx.getSql(),true);\r\n\t\t\t}\r\n\t\t} else {//单表或者分库表\r\n\t\t\tif (!checkRuleRequired(schema, ctx, routeUnit, tc)) {\r\n\t\t\t\tthrow new IllegalArgumentException(\"route rule for table \"\r\n\t\t\t\t\t\t+ tc.getName() + \" is required: \" + ctx.getSql());\r\n\r\n\t\t\t}\r\n\t\t\tif(tc.getPartitionColumn() == null && !tc.isSecondLevel()) {//单表且不是childTable\r\n//\t\t\t\treturn RouterUtil.routeToSingleNode(rrs, tc.getDataNodes().get(0),ctx.getSql());\r\n\t\t\t\treturn routeToMultiNode(rrs.isCacheAble(), rrs, tc.getDataNodes(), ctx.getSql());\r\n\t\t\t} else {\r\n\t\t\t\t//每个表对应的路由映射\r\n\t\t\t\tMap<String,Set<String>> tablesRouteMap = new HashMap<String,Set<String>>();\r\n\t\t\t\tif(routeUnit.getTablesAndConditions() != null && routeUnit.getTablesAndConditions().size() > 0) {\r\n\t\t\t\t\tRouterUtil.findRouteWithcConditionsForTables(schema, rrs, routeUnit.getTablesAndConditions(), tablesRouteMap, ctx.getSql(), cachePool, isSelect);\r\n\t\t\t\t\tif(rrs.isFinishedRoute()) {\r\n\t\t\t\t\t\treturn rrs;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif(tablesRouteMap.get(tableName) == null) {\r\n\t\t\t\t\treturn routeToMultiNode(rrs.isCacheAble(), rrs, tc.getDataNodes(), ctx.getSql());\r","sourceCodeStart":1377,"sourceCodeEnd":1413,"githubUrl":"https://github.com/MyCATApache/Mycat-Server/blob/65f8d8beb752f935752f2a0eec0ab017facab9ef/src/main/java/io/mycat/route/util/RouterUtil.java#L1377-L1413","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"-- before\nINSERT INTO orders(order_id, amount) VALUES(1001, 50);\n-- after (include partition column 'customer_id')\nINSERT INTO orders(order_id, customer_id, amount) VALUES(1001, 5, 50);","handlingStrategy":"validation","validationCode":"// Ensure the partition column is present in INSERT column list before sending\nif (!insertColumns.contains(tc.getPartitionColumn())) throw new IllegalArgumentException(\"shard key required: \" + tc.getPartitionColumn());","typeGuard":null,"tryCatchPattern":"try { rrs = route(...); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith(\"route rule for table\")) { LOG.warn(\"missing partition column in statement\", e); } throw e; }","preventionTips":["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"],"tags":["sharding","insert","routing"],"backgroundTag":"missing-required-argument","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"}