MyCATApache/Mycat-Server · error · SQLNonTransientException
can't find table define in schema + tableName + schema: +…
Error message
can't find table define in schema + tableName + schema: + schema.getName()
What it means
RouterUtil iterates over tablesAndConditions (table -> column conditions) during multi-table route calculation and looks up each table's TableConfig in the schema. Any table not declared in schema.xml (lookup is done on the uppercased name) causes a SQLNonTransientException, since MyCat cannot route tables it has no definition for.
Solutions
- Declare every table referenced in the query in schema.xml and reload MyCat
- Match table-name case with the schema.xml declaration (MyCat uppercases for lookup)
- Add a schema-level default dataNode as fallback for undeclared tables
- Verify the connection's logical schema contains all tables your SQL references
Example fix
// before SELECT * FROM orders o JOIN items i ON ...; // 'items' undeclared // after (schema.xml) <table name="items" dataNode="dn1"/>
Defensive patterns
Strategy: validation
Validate before calling
// verify all tables referenced by a join are declared in MyCat
for (String t : List.of("ORDERS","ITEMS")) {
ResultSet rs = stmt.executeQuery("SHOW TABLES LIKE '" + t + "'");
if (!rs.next()) throw new IllegalStateException("Table not in MyCat schema: " + t);
} Try / catch
try {
execute(joinSql);
} catch (SQLNonTransientException e) {
if (e.getMessage().startsWith("can't find table define in schema"))
throw new IllegalStateException("Declare all joined tables in schema.xml", e);
throw e;
} Prevention
- Keep every join participant declared in schema.xml
- Normalize table-name case in SQL generation (uppercase) to match MyCat lookups
- Run a config-completeness test comparing schema.xml tables against DB tables in CI
When it happens
Trigger: Executing a JOIN/multi-table query where at least one referenced table has no <table> entry in the current MyCat schema; lookup key is the uppercased table name from the parsed SQL.
Common situations: Joining against a table present only in backend MySQL; case mismatch between SQL table name and schema.xml declaration; wrong schema selected; table added to DB but config never reloaded.
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 + alias:+…
- can't find table define in schema + tableName + schema: +…
- Can't find a valid data node for specified node index : +…
- can't find any valid datanode : -> ->
- can't find any valid datanode : + tableConfig.getName() + …
AI-assisted analysis of MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11).
Data as JSON: /api/errors/cc3416c528187975.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/io/mycat/route/util/RouterUtil.java:1611
return nodes;
}
/**
* 处理分库表路由
*/
public static void findRouteWithcConditionsForTables(SchemaConfig schema, RouteResultset rrs,
Map<String, Map<String, Set<ColumnRoutePair>>> tablesAndConditions,
Map<String, Set<String>> tablesRouteMap, String sql, LayerCachePool cachePool, boolean isSelect)
throws SQLNonTransientException {
//为分库表找路由
for(Map.Entry<String, Map<String, Set<ColumnRoutePair>>> entry : tablesAndConditions.entrySet()) {
String tableName = entry.getKey().toUpperCase();
TableConfig tableConfig = schema.getTables().get(tableName);
if(tableConfig == null) {
String msg = "can't find table define in schema "
+ tableName + " schema:" + schema.getName();
LOGGER.warn(msg);
throw new SQLNonTransientException(msg);
}
if(tableConfig.getDistTables()!=null && tableConfig.getDistTables().size()>0){
routeToDistTableNode(schema,rrs,sql, tablesAndConditions, cachePool,isSelect, entry);
}
//全局表或者不分库的表略过(全局表后面再计算)
if(tableConfig.isGlobalTable() || schema.getTables().get(tableName).getDataNodes().size() == 1) {
continue;
} else {//非全局表:分库表、childTable、其他
Map<String, Set<ColumnRoutePair>> columnsMap = entry.getValue();
String joinKey = tableConfig.getJoinKey();
String partionCol = tableConfig.getPartitionColumn();
String primaryKey = tableConfig.getPrimaryKey();
boolean isFoundPartitionValue = partionCol != null && entry.getValue().get(partionCol) != null;
boolean isLoadData=false;
if (LOGGER.isDebugEnabled()
&& sql.startsWith(LoadData.loadDataHint)||rrs.isLoadData()) {
//由于load data一次会计算很多路由数据,如果输出此日志会极大降低load data的性能
View on GitHub (pinned to 65f8d8beb7)