MyCATApache/Mycat-Server · error · RuntimeException

crc32slot_ .properties does not match schema table dataNode.

Error message

crc32slot_%s.properties does not match schema table dataNode.

What it means

balanceExpand redistributes slots of crc32slot_%s.properties across new data nodes. When it needs to take a task from oldDataNodes index i but i has run past the list, the rule file's dataNode list and the schema's table dataNodes disagree, so it throws this formatted error naming the table. This is a consistency guard against a stale/incomplete slot rule file.

Solutions

  1. Regenerate crc32slot_<TABLE>.properties to match the current dataNode list in schema.xml (rebuild the rule file or use MyCAT's rule regeneration tooling).
  2. Ensure table name casing matches: the error uses table.toUpperCase(), verify the properties file uses the same naming.
  3. Align schema.xml dataNodes with the from/to nodes in the rule file before rerunning balanceExpand.
  4. Back up and hand-merge the rule file only if regeneration is impossible, keeping dataNode count equal on both sides.

Example fix

// before
if (i >= oldDataNodes.size()) {
    throw new RuntimeException(String.format("crc32slot_%s.properties does not match schema table dataNode.", table.toUpperCase()));
}
// after
// regenerate the rule file first:
// java -cp mycat.jar io.mycat.util.RegenCrc32SlotRule <schema> <table>
// then rerun balanceExpand with matching dataNodes
Defensive patterns

Strategy: validation

Validate before calling

// compare rule file dataNodes vs schema.xml before expansion
Properties rule = loadProperties("crc32slot_" + table.toUpperCase() + ".properties");
Set<String> ruleNodes = rule.stringPropertyNames().stream().map(k -> k.split("=")[0]).collect(toSet());
Set<String> schemaNodes = getDataNodesFromSchemaXml(table);
if (!ruleNodes.containsAll(schemaNodes)) throw new IllegalStateException("rule file out of sync with schema.xml");

Prevention

When it happens

Trigger: crc32slot_<TABLE>.properties references fewer dataNodes than schema.xml defines for the table; the rule file was edited or copied from another table; nodes were added to schema.xml without regenerating the rule file; case mismatch on the table name used to locate the file.

Common situations: Manual edits to conf/crc32slot files after scaling out; migration run against a schema whose rule file was generated before adding dataNodes; copying rule files between environments.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at src/main/java/io/mycat/migrate/MigrateUtils.java:65

        for (int i = 0; i < integerListMap.size(); i++) {

            List<Range> rangeList = integerListMap.get(i);
            int needMoveNum = getCurTotalSize(rangeList) - newSlotPerNode;
            List<Range> allMoveList = getPartAndRemove(rangeList, needMoveNum);
            for (int i1 = 0; i1 < newDataNodes.size(); i1++) {
                String newDataNode = newDataNodes.get(i1);
                if (allMoveList.size() == 0)
                    break;
                List<MigrateTask> curRangeList = newNodeTask.get(newDataNode);
                if (curRangeList == null)
                    curRangeList = new ArrayList<>();
                int hasSlots = getCurTotalSizeForTask(curRangeList);
                int needMove = (i1 == 0) ? newSlotPerNode - hasSlots + gb : newSlotPerNode - hasSlots;
                if (needMove > 0) {
                    List<Range> moveList = getPartAndRemove(allMoveList, needMove);
                    MigrateTask task = new MigrateTask();
                    if (i >= oldDataNodes.size()) {
                        throw new RuntimeException(String.format("crc32slot_%s.properties does not match schema table dataNode.", table.toUpperCase()));
                    }
                    task.setFrom(oldDataNodes.get(i));
                    task.setTo(newDataNode);
                    task.setTable(table);
                    task.setSlots(moveList);
                    curRangeList.add(task);
                    newNodeTask.put(newDataNode, curRangeList);
                }
            }

            if (allMoveList.size() > 0) {
                throw new RuntimeException("some slot has not moved to");
            }
        }
        return newNodeTask;
    }

View on GitHub (pinned to 65f8d8beb7)