MyCATApache/Mycat-Server · error · SQLNonTransientException
can't find table define in schema + tableName + alias:+…
Error message
can't find table define in schema + tableName + alias:+ alias + , schema: + schema.getName()
What it means
During query routing with a table alias, RouterUtil resolves the (alias-stripped) table name against the current schema's TableConfig map. If the table is not defined in the MyCat schema config and the schema has no default dataNode, routing cannot proceed and it throws SQLNonTransientException.
Solutions
- Add the missing table to schema.xml: <table name="tableName" dataNode="dn1" .../> and reload MyCat config
- Add a default dataNode to the schema so undeclared tables can be routed: <schema name="..." dataNode="dn1">
- Verify table name spelling and case (MyCat uppercases table names when looking up)
- Check you are connected to the intended logical schema in MyCat
Example fix
// before (schema.xml) <schema name="testdb"> <table name="orders" dataNode="dn1"/> </schema> // after <schema name="testdb"> <table name="orders" dataNode="dn1"/> <table name="customers" dataNode="dn1"/> </schema>
Defensive patterns
Strategy: validation
Validate before calling
// before executing, verify the table is declared in MyCat
try (ResultSet rs = stmt.executeQuery("SHOW TABLES")) {
Set<String> known = new HashSet<>();
while (rs.next()) known.add(rs.getString(1).toUpperCase());
if (!known.contains(tableName.toUpperCase()))
throw new IllegalStateException(tableName + " not declared in MyCat schema");
} Try / catch
try {
return route(query);
} catch (SQLNonTransientException e) {
if (e.getMessage().startsWith("can't find table define in schema")) {
throw new ConfigurationException("Declare table in schema.xml: " + e.getMessage(), e);
}
throw e;
} Prevention
- Keep schema.xml and the real MySQL schema in sync; automate config generation from information_schema
- Always use consistent table-name casing between SQL and schema.xml
- Reload MyCat config (reload @@config) after adding tables
- Pin application connections to the intended MyCat logical schema
When it happens
Trigger: Running a SELECT (or other routed statement) that references table 'tableName' with alias 'alias', where schema.xml has no <table name="tableName"> under the schema and the schema lacks a dataNode attribute.
Common situations: Table exists in MySQL but was never declared in MyCat's schema.xml; typo in table name or case mismatch; connecting to the wrong MyCat logical schema; recently added table not reloaded into config.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- can't find table define in schema + tableName + schema: +…
- can't find table define in schema + tableName + schema: +…
- "bad insert sql columnSize != valueSize:" + columnNum + "…
- bad insert sql columnSize != valueSize:values:
- "bad insert sql (sharding column:"+ partitionColumn + " not…
AI-assisted analysis of MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11).
Data as JSON: /api/errors/0d81588a41b9f2bf.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/io/mycat/route/util/RouterUtil.java:1263
//为全局表和单库表找路由
for(String tableName : tables) {
TableConfig tableConfig = schema.getTables().get(tableName.toUpperCase());
if(tableConfig == null) {
//add 如果表读取不到则先将表名从别名中读取转化后再读取
String alias = ctx.getTableAliasMap().get(tableName);
if(!StringUtil.isEmpty(alias)){
tableConfig = schema.getTables().get(alias.toUpperCase());
}
if(tableConfig == null){
if (StringUtils.isNotEmpty(schema.getDataNode())) {
return routeToSingleNode(rrs, schema.getDataNode(), ctx.getSql());
} else {
String msg = "can't find table define in schema " + tableName + " alias:" + alias + ", schema:"
+ schema.getName();
LOGGER.warn(msg);
throw new SQLNonTransientException(msg);
}
}
}
if(tableConfig.isGlobalTable()) {//全局表
if(tablesRouteMap.get(tableName) == null) {
tablesRouteMap.put(tableName, new HashSet<String>());
}
tablesRouteMap.get(tableName).addAll(tableConfig.getDataNodes());
} else if(tablesRouteMap.get(tableName) == null) { //余下的表都是单库表
tablesRouteMap.put(tableName, new HashSet<String>());
tablesRouteMap.get(tableName).addAll(tableConfig.getDataNodes());
}
if(tableConfig.getDistTables().size() > 0) {
Map<String, List<String>> subTablesmap = rrs.getSubTableMaps();
if (subTablesmap == null) {
View on GitHub (pinned to 65f8d8beb7)