MyCATApache/Mycat-Server · error · SQLSyntaxErrorException
sub table not exists for on
Error message
sub table not exists for on
What it means
For a distributed (dist) table, parserBatchInsert routes to the first datanode and then looks up the physical sub-table name via tableConfig.getDistTables().get(nodeIndex). If getDistTables() is null — the dist table mapping is not configured — it throws SQLSyntaxErrorException stating the sub table doesn't exist for the datanode on the logical table.
Solutions
- Add the distTables configuration (sub-table name list) for the table in schema.xml and reload MyCat
- Verify the table definition actually is a dist table; if not, remove the isDistTable/distTable flag
- Confirm the target datanode's physical schema contains the expected sub-table
- Re-run the dist table setup/migration script that registers sub-tables
Example fix
// before (schema.xml) <table name="order" distTable="true" dataNode="dn1"/> // after <table name="order" distTable="true" dataNode="dn1"> <childTable name="order_0"/><childTable name="order_1"/> </table>
Defensive patterns
Strategy: validation
Validate before calling
TableConfig tc = schema.getTables().get(table.toUpperCase()); if (tc != null && tc.isDistTable() && tc.getDistTables() == null) throw new IllegalStateException("distTables not configured"); Try / catch
try { route(sql); } catch (SQLSyntaxErrorException e) { if (e.getMessage().contains("sub table not exists")) { reloadSchemaConfig(); } else throw e; } Prevention
- Validate schema.xml at startup: every distTable must have distTables mappings
- Keep a smoke-test INSERT per logical table in CI
- Version-control schema.xml and review dist-table changes
- Reload MyCat config after edits before running writes
When it happens
Trigger: statementParse -> parserBatchInsert on an INSERT into a tableConfig.isDistTable()==true table where schema.xml defines the table as distTable but the distTables sub-table list is missing/null.
Common situations: Incomplete schema.xml: table marked with distTable attribute but sub-table mappings not generated/declared; typo in the table name so config loaded partially; copying a dist-table config to a cluster where sub-tables were never created.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- only one rule can defined
- can't find function of name
- table rule coulmns has multi values
- rule function duplicated!
- nameSuffix , require name parameter cannot multiple breaks!
AI-assisted analysis of MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11).
Data as JSON: /api/errors/2cfc99a483b4a1b2.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/io/mycat/route/parser/druid/impl/DruidInsertParser.java:291
nodeValuesMap.get(nodeIndex).add(valueClause);
}
RouteResultsetNode[] nodes = new RouteResultsetNode[nodeValuesMap.size()];
int count = 0;
for(Map.Entry<Integer,List<ValuesClause>> node : nodeValuesMap.entrySet()) {
Integer nodeIndex = node.getKey();
List<ValuesClause> valuesList = node.getValue();
insertStmt.getValuesList().clear();
insertStmt.getValuesList().addAll(valuesList);
// insertStmt.setValuesList(valuesList);
if(tableConfig.isDistTable()) {
nodes[count] = new RouteResultsetNode(tableConfig.getDataNodes().get(0),
rrs.getSqlType(),insertStmt.toString());
if(tableConfig.getDistTables()==null){
String msg = " sub table not exists for " + nodes[count].getName() + " on " + tableName;
LOGGER.error("DruidMycatRouteStrategyError " + msg);
throw new SQLSyntaxErrorException(msg);
}
String subTableName = tableConfig.getDistTables().get(nodeIndex);
nodes[count].setSubTableName(subTableName);
SQLInsertStatement insertStatement = (SQLInsertStatement) insertStmt;
SQLExprTableSource tableSource = insertStatement.getTableSource();
//getDisTable 修改表名称
SQLIdentifierExpr sqlIdentifierExpr = new SQLIdentifierExpr();
sqlIdentifierExpr.setParent(tableSource.getParent());
sqlIdentifierExpr.setName(subTableName);
SQLExprTableSource from2 = new SQLExprTableSource(sqlIdentifierExpr);
insertStatement.setTableSource(from2);
nodes[count].setStatement(insertStatement.toString());
} else {
nodes[count] = new RouteResultsetNode(tableConfig.getDataNodes().get(nodeIndex),
rrs.getSqlType(),insertStmt.toString());
}
View on GitHub (pinned to 65f8d8beb7)