MyCATApache/Mycat-Server · error · IllegalArgumentException

ruleRequired but rule is null

Error message

ruleRequired but rule is null

What it means

TableConfig enforces consistency between the ruleRequired flag and the sharding rule: if ruleRequired is true, a RuleConfig must be supplied. When ruleRequired is true but rule is null, IllegalArgumentException is thrown, because a table declared to require a rule cannot be routed without one.

Solutions

  1. Set the rule attribute on the <table> element to a defined tableRule name.
  2. Ensure the function referenced by the tableRule exists in rule.xml.
  3. If the table truly has no sharding rule, set ruleRequired="false" on the table element.

Example fix

// before (schema.xml)
<table name="orders" dataNode="dn1" ruleRequired="true" />
// after
<table name="orders" dataNode="dn1" rule="order-rule" ruleRequired="true" />
Defensive patterns

Strategy: validation

Validate before calling

if (ruleRequired && rule == null) throw new IllegalArgumentException("table " + tableName + " sets ruleRequired but has no rule");

Try / catch

try { new TableConfig(...); } catch (IllegalArgumentException e) { if (e.getMessage().contains("ruleRequired")) { LOG.error("Add rule attr or set ruleRequired=false"); } throw e; }

Prevention

When it happens

Trigger: new TableConfig(..., ruleRequired=true, rule=null, ...) — e.g. a <table> element declaring ruleRequired but the referenced tableRule/function is missing or failed to load.

Common situations: schema.xml table with ruleRequired="true" but no rule attribute; the rule's function name not matching any function defined in rule.xml; rule loading failure earlier in startup.

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/0c98d495c2d34575. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/io/mycat/config/model/TableConfig.java:82

    private ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock(false);

    public TableConfig(String tableName, String primaryKey, boolean autoIncrement, boolean needAddLimit, int tableType,
                       String dataNode, Set<String> dbType, RuleConfig rule, boolean ruleRequired,
                       TableConfig parentTC, boolean isChildTable, String joinKey,
                       String parentKey, String subTables, boolean fetchStoreNodeByJdbc) {
        if (tableName == null) {
            throw new IllegalArgumentException("table name is null");
        } else if (dataNode == null) {
            throw new IllegalArgumentException("dataNode name is null");
        }
        this.primaryKey = primaryKey;
        this.autoIncrement = autoIncrement;
        this.needAddLimit = needAddLimit;
        this.fetchStoreNodeByJdbc = fetchStoreNodeByJdbc;
        this.tableType = tableType;
        this.dbTypes = dbType;
        if (ruleRequired && rule == null) {
            throw new IllegalArgumentException("ruleRequired but rule is null");
        }

        this.name = tableName.toUpperCase();
        String theDataNodes[] = SplitUtil.split(dataNode, ',', '$', '-');
        if (theDataNodes == null || theDataNodes.length <= 0) {
            throw new IllegalArgumentException("invalid table dataNodes: " + dataNode);
        }
        dataNodes = new ArrayList<String>(theDataNodes.length);
        for (String dn : theDataNodes) {
            dataNodes.add(dn);
        }

        if (subTables != null && !subTables.equals("")) {
            String sTables[] = SplitUtil.split(subTables, ',', '$', '-');
            if (sTables == null || sTables.length <= 0) {
                throw new IllegalArgumentException("invalid table subTables");
            }
            this.distTables = new ArrayList<String>(sTables.length);

View on GitHub (pinned to 65f8d8beb7)