MyCATApache/Mycat-Server · error · RuntimeException

please make sure the primaryKey's config is not null in…

Error message

please make sure the primaryKey's config is not null in schemal.xml

What it means

isPKInFields parses an INSERT's column list to locate the primary key's position, but the primaryKey argument itself is null because the table's configuration lacks a primaryKey. The method throws RuntimeException immediately since primary-key-based routing cannot proceed without it. Note the message says 'schemal.xml' but it refers to schema.xml.

Solutions

  1. Add primaryKey="<column>" to the table's <table> definition in schema.xml and reload the config
  2. If PK routing is not needed, ensure the insert routing path does not rely on primaryKey (e.g. configure a proper sharding rule on an existing column)
  3. Update the code/config so the table uses childTable/parent key routing only when the parent's primaryKey is defined

Example fix

// before (schema.xml)
<table name="t_order" dataNode="dn1,dn2" rule="mod-rule"/>
// after
<table name="t_order" dataNode="dn1,dn2" rule="mod-rule" primaryKey="id"/>
Defensive patterns

Strategy: validation

Validate before calling

TableConfig tc = schema.getTables().get(tableName);
if (tc == null || tc.getPrimaryKey() == null || tc.getPrimaryKey().isEmpty()) {
  throw new IllegalStateException("table " + tableName + " needs primaryKey in schema.xml");
}

Try / catch

try { routeInsert(...); } catch (RuntimeException e) { if (e.getMessage().contains("primaryKey")) { /* fix schema.xml */ } throw e; }

Prevention

When it happens

Trigger: Executing an INSERT against a sharded table that uses the primary key for routing (or child-table join-key logic) while the <table> entry in schema.xml has no primaryKey attribute, and code path routeToMultiNode...insert calls isPKInFields with tableConfig.getPrimaryKey() == null.

Common situations: Declaring a sharded <table> with rule based on a column but omitting primaryKey="id"; after adding a new table to schema.xml without the primaryKey attribute; autoincrement/sequence features requiring PK not configured.

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


AI-assisted analysis of MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11). Data as JSON: /api/errors/9b43b206f2c616a4. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/io/mycat/route/util/RouterUtil.java:610

			String origSQL, ServerConnection sc) throws SQLNonTransientException {
		String tableName = StringUtil.getTableName(origSQL).toUpperCase();
		TableConfig tableConfig = schema.getTables().get(tableName);
		boolean processedInsert=false;
		//判断是有自增字段
		if (null != tableConfig && tableConfig.isAutoIncrement()) {
			String primaryKey = tableConfig.getPrimaryKey();
			processedInsert=processInsert(sc,schema,sqlType,origSQL,tableName,primaryKey);
		}
		return processedInsert;
	}
	/*
	 *  找到返回主键的的位置
	 *  找不到返回 -1
	 * */
	private static int isPKInFields(String origSQL,String primaryKey,int firstLeftBracketIndex,int firstRightBracketIndex){

		if (primaryKey == null) {
			throw new RuntimeException("please make sure the primaryKey's config is not null in schemal.xml");
		}

		boolean isPrimaryKeyInFields = false;
		int  pkStart = 0;
		String upperSQL = origSQL.substring(firstLeftBracketIndex, firstRightBracketIndex + 1).toUpperCase();
		for (int pkOffset = 0, primaryKeyLength = primaryKey.length();;) {
			pkStart = upperSQL.indexOf(primaryKey, pkOffset);
			if (pkStart >= 0 && pkStart < firstRightBracketIndex) {
				char pkSide = upperSQL.charAt(pkStart - 1);
				if (pkSide <= ' ' || pkSide == '`' || pkSide == ',' || pkSide == '(') {
					pkSide = upperSQL.charAt(pkStart + primaryKey.length());
					isPrimaryKeyInFields = pkSide <= ' ' || pkSide == '`' || pkSide == ',' || pkSide == ')';
				}
				if (isPrimaryKeyInFields) {
					break;
				}
				pkOffset = pkStart + primaryKeyLength;
			} else {

View on GitHub (pinned to 65f8d8beb7)