MyCATApache/Mycat-Server · error · SQLNonTransientException
can't find table define in schema schema:
Error message
can't find table define in schema schema:
What it means
The insert parser looks up the target table in the loaded schema configuration (schema.getTables()). If the table name from the INSERT is not defined in Mycat's schema.xml, no TableConfig exists and routing cannot proceed, so a SQLNonTransientException is thrown naming the table and schema. Mycat only routes tables it knows about.
Solutions
- Add a <table> entry for the table in schema.xml under the correct schema, with dataNode/rule attributes.
- Reload Mycat configuration (server restart or reload @@config) so the new table definition is picked up.
- Match the case of the table in the INSERT to the schema.xml definition (Mycat compares uppercase names).
Example fix
// before (schema.xml) <schema name="TESTDB"> <table name="orders" dataNode="dn1" rule="rule1"/> </schema> // after — add the missing table <schema name="TESTDB"> <table name="orders" dataNode="dn1" rule="rule1"/> <table name="order_items" dataNode="dn1,dn2" rule="rule1"/> </schema>
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check the table is configured before issuing the INSERT
String table = "ORDER_ITEMS"; // upper-cased table name
// after load: Map<String, TableConfig> tables = schema.getTables();
if (!tables.containsKey(table)) {
throw new IllegalStateException("Table not declared in Mycat schema.xml: " + table);
} Try / catch
try {
stmt.execute(insertSql);
} catch (SQLNonTransientException e) {
if (e.getMessage().startsWith("can't find table define in schema")) {
// fix schema.xml and reload config, then retry
} else { throw e; }
} Prevention
- Keep schema.xml table entries in sync with backend MySQL schema; reload config after edits.
- Use consistent uppercase table names in SQL and config.
When it happens
Trigger: INSERT against a table absent from schema.xml (no <table> entry in the referenced schema); table name case mismatch after uppercasing (Mycat compares upper-cased names); using a schema name different from the configured one.
Common situations: Table created on MySQL backends but not declared in schema.xml; hot reload not performed after editing schema.xml; lowercase vs uppercase table-name mismatch in config; inserting into an unconfigured global/child table.
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 table define in schema + tableName + schema: +…
- "can't find table define of " + table + " in schema:" +…
AI-assisted analysis of MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11).
Data as JSON: /api/errors/2a94638a362191e7.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/io/mycat/route/parser/druid/impl/DruidInsertParser.java:64
*/
@Override
public void statementParse(SchemaConfig schema, RouteResultset rrs, SQLStatement stmt) throws SQLNonTransientException {
MySqlInsertStatement insert = (MySqlInsertStatement)stmt;
String tableName = StringUtil.removeBackquote(insert.getTableName().getSimpleName()).toUpperCase();
ctx.addTable(tableName);
if(RouterUtil.isNoSharding(schema,tableName)) {//整个schema都不分库或者该表不拆分
RouterUtil.routeForTableMeta(rrs, schema, tableName, rrs.getStatement());
rrs.setFinishedRoute(true);
return;
}
TableConfig tc = schema.getTables().get(tableName);
if(tc == null) {
String msg = "can't find table define in schema "
+ tableName + " schema:" + schema.getName();
LOGGER.warn(msg);
throw new SQLNonTransientException(msg);
} else {
//childTable的insert直接在解析过程中完成路由
if (tc.isChildTable()) {
parserChildTable(schema, rrs, tableName, insert);
return;
}
String partitionColumn = tc.getPartitionColumn();
if(partitionColumn != null) {//分片表
//拆分表必须给出column list,否则无法寻找分片字段的值
if(insert.getColumns() == null || insert.getColumns().size() == 0) {
throw new SQLSyntaxErrorException("partition table, insert must provide ColumnList");
}
//批量insert
if(isMultiInsert(insert)) {
// String msg = "multi insert not provided" ;View on GitHub (pinned to 65f8d8beb7)