MyCATApache/Mycat-Server · error · RuntimeException

${e}

Error message

${e}

What it means

In modifyRuleData's finally block, releasing the ZK distributed lock (ruleDataLock.release()) can itself throw (lock already released, session expired, connection lost). That exception is wrapped in a RuntimeException from the finally block, masking the method's normal result. This occurs while updating the rule data during switch commit.

Solutions

  1. Check the 'Caused by' KeeperException: if session expired, verify ZK connectivity and retry the switch commit.
  2. Ensure release() is only called by the lock owner and not twice (guard with a flag or tryAcquire result).
  3. Increase ZK session timeout if rule modification runs long.
  4. Wrap release in a second try/catch that logs instead of throwing, so cleanup failures don't mask the commit result.

Example fix

// before
} catch (Exception e) {
    throw new RuntimeException(e);
}
// after
} catch (Exception e) {
    log.warn("Failed to release ruleDataLock", e); // do not mask commit result
}
Defensive patterns

Strategy: try-catch

Validate before calling

// confirm ZK session alive before starting rule modification
if (client.getState() != CuratorFrameworkState.STARTED || !isSessionAlive(client)) {
    throw new IllegalStateException("ZK session not healthy for lock use");
}

Try / catch

try {
    ruleDataLock.acquire();
    modifyRuleData(prop, task, nodes);
} catch (Exception e) {
    // real failure handling
} finally {
    try { ruleDataLock.release(); } catch (Exception rel) { log.warn("lock release failed", rel); }
}

Prevention

When it happens

Trigger: ZooKeeper session expired or closed before release(); release() called on an already-released InterProcessMutex; ZK ensemble unreachable at commit time.

Common situations: Long-running rule modification exceeding the ZK session timeout; concurrent switch attempts double-releasing the lock; ZK network blip exactly during commit.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at src/main/java/io/mycat/migrate/SwitchCommitListener.java:344

            byte[] ruleData = zk.getData().forPath(rulePath);
            Properties prop = new Properties();
            prop.load(new ByteArrayInputStream(ruleData));
            for (MigrateTask migrateTask : allTaskList) {
                modifyRuleData(prop, migrateTask, allNewDataNodes);
            }
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            prop.store(out, "WARNING   !!!Please do not modify or delete this file!!!");
            if (transactionFinal == null) {
                transactionFinal = ZKUtils.getConnection().inTransaction().setData().forPath(rulePath, out.toByteArray()).and();
            } else {
                transactionFinal.setData().forPath(rulePath, out.toByteArray());
            }
        } finally {
            try {
                if (ruleDataLock != null)
                    ruleDataLock.release();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return transactionFinal;
    }

    private void modifyRuleData(Properties prop, MigrateTask task, List<String> allNewDataNodes) {
        int fromIndex = -1;
        int toIndex = -1;
        List<String> dataNodes = allNewDataNodes;
        for (int i = 0; i < dataNodes.size(); i++) {
            String dataNode = dataNodes.get(i);
            if (dataNode.equalsIgnoreCase(task.getFrom())) {
                fromIndex = i;
            } else if (dataNode.equalsIgnoreCase(task.getTo())) {
                toIndex = i;
            }
        }
        String from = prop.getProperty(String.valueOf(fromIndex));

View on GitHub (pinned to 65f8d8beb7)