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
- Check the 'Caused by' KeeperException: if session expired, verify ZK connectivity and retry the switch commit.
- Ensure release() is only called by the lock owner and not twice (guard with a flag or tryAcquire result).
- Increase ZK session timeout if rule modification runs long.
- 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
- Always release the lock in its own try/catch so cleanup never masks the result
- Keep ZK session timeout well above rule-modification duration
- Only release a lock you actually acquired
- Retry switch commit on session-expired release failures after reconnect
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
- ${e}
- failed to connect to zookeeper service
- can't find myid properties file
- clusterId and zkURL and myid must not be null or empty!
- IncrSequenceZKHandler should be loaded first!
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)