MyCATApache/Mycat-Server · error · SQLNonTransientException

"can't find table define in schema " + tableName + "…

Error message

"can't find table define in schema " + tableName + " schema:" + schema.getName()

What it means

The insert parser looks up the table name from the INSERT statement in the schema configuration (schema.xml tables map). If no TableConfig exists for that table, Mycat cannot determine datanodes/sharding rules, so it throws SQLNonTransientException.

Solutions

  1. Add a <table> entry for the table in schema.xml (with its datanodes and rule) and reload/restart Mycat
  2. Verify the client connected to the intended schema (schema name in the message)
  3. Check the table name spelling and case matches schema.xml exactly (names are uppercased before lookup)
  4. If the table lives only on one node, ensure it is still declared in schema.xml, or route it via a schema entry with no rule

Example fix

// before (schema.xml)
<schema name="db">
  <table name="t1" dataNode="dn1"/>
</schema>
// after
<schema name="db">
  <table name="t1" dataNode="dn1"/>
  <table name="t2" dataNode="dn1,dn2" rule="rule1"/>
</schema>
Defensive patterns

Strategy: validation

Validate before calling

// verify table is declared before inserting
SchemaConfig schema = MycatServer.getInstance().getConfig().getSchemas().get(currentSchema);
String table = sqlTableName.toUpperCase();
if (schema == null || !schema.getTables().containsKey(table)) {
    throw new IllegalStateException("Table not defined in schema.xml: " + table);
}

Type guard

static TableConfig requireTable(SchemaConfig schema, String tableName) {
    TableConfig tc = schema.getTables().get(tableName);
    if (tc == null) throw new IllegalStateException("can't find table define in schema " + tableName);
    return tc;
}

Try / catch

try {
    routeResult = route(insertSql);
} catch (SQLNonTransientException e) {
    if (e.getMessage().startsWith("can't find table define in schema")) {
        throw new ConfigurationException("Declare the table in schema.xml or connect to the correct schema", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Executing INSERT INTO <tbl> ... where <tbl> (uppercased, backquotes stripped) is absent from schema.getTables(); typically the table is not declared in schema.xml or the wrong logical schema is targeted by the connection.

Common situations: Table added to backend MySQL but not to schema.xml; connecting to the wrong Mycat schema; case-sensitivity mismatch between SQL table name and schema.xml table declaration; typo in table name.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11). Data as JSON: /api/errors/a013753be2c9923d. 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)