alibaba/canal · error · ZkException
zookeeper_create_error, serveraddrs={}
Error message
zookeeper_create_error, serveraddrs={} What it means
Thrown by ZooKeeperx.configMutliCluster when merging additional ZK cluster address lists via reflection fails. configMutliCluster only runs when the connect string contains ';' (multi-cluster fallback). It reflectively appends a second cluster's InetSocketAddress list into the first ZooKeeper's HostProvider; any reflection or address-parse failure closes the zk handle and throws ZkException carrying the first cluster string. This usually indicates an incompatible ZooKeeper client version (reflection field names changed) or a malformed second-cluster connect string.
Source
Thrown at common/src/main/java/com/alibaba/otter/canal/common/zookeeper/ZooKeeperx.java:117
String cluster = _serversList.get(i);
// 强制获取zk中的地址信息
ClientCnxn cnxn = (ClientCnxn) ReflectionUtils.getField(clientCnxnField, zk);
HostProvider hostProvider = (HostProvider) ReflectionUtils.getField(hostProviderField, cnxn);
List<InetSocketAddress> serverAddrs = (List<InetSocketAddress>) ReflectionUtils.getField(serverAddressesField,
hostProvider);
// 添加第二组集群列表
serverAddrs.addAll(new ConnectStringParser(cluster).getServerAddresses());
}
}
} catch (Exception e) {
try {
if (zk != null) {
zk.close();
}
} catch (InterruptedException ie) {
// ignore interrupt
}
throw new ZkException("zookeeper_create_error, serveraddrs=" + cluster1, e);
}
}
}
View on GitHub (pinned to 87be50e876)
Solutions
- Use a single ZK ensemble (no ';') if multi-cluster failover is not required — configMutliCluster returns early and the failure path is skipped.
- Ensure the zookeeper client jar version matches the one canal was built/tested against (check pom dependency versions) so reflective fields exist.
- Validate the second cluster connect string (host:port pairs, comma-separated) is syntactically correct.
- If you need multi-cluster failover, pin the exact supported zookeeper version or avoid this proprietary multi-cluster feature.
Example fix
# before canal.zkServers = zk-hz-1:2181,zk-hz-2:2181;zk-us-1:2181,zk-us-2:notaport # after canal.zkServers = zk-hz-1:2181,zk-hz-2:2181,zk-hz-3:2181
Defensive patterns
Strategy: validation
Validate before calling
// Validate multi-cluster connect string shape before constructing ZooKeeperx
void validateMultiCluster(String zkServers) {
if (zkServers == null || zkServers.trim().isEmpty()) {
throw new IllegalArgumentException("canal.zkServers is empty");
}
for (String cluster : zkServers.split(";")) {
for (String hp : cluster.split(",")) {
String[] parts = hp.split(":");
if (parts.length != 2 || !parts[1].matches("\\d+")) {
throw new IllegalArgumentException("bad ZK host:port " + hp);
}
}
}
} Try / catch
try {
new ZooKeeperx(zkServers).connect(watcher);
} catch (org.I0Itec.zkclient.exception.ZkException e) {
if (e.getMessage().startsWith("zookeeper_create_error")) {
// multi-cluster merge failed: fall back to a single ensemble
new ZooKeeperx(firstClusterOnly(zkServers)).connect(watcher);
} else throw e;
} Prevention
- Pin the zookeeper client jar version canal was built against to avoid reflective-field drift.
- Prefer a single resilient ensemble over the ';' multi-cluster feature unless required.
- Validate each ';' cluster segment parses to host:port pairs.
When it happens
Trigger: canal.zkServers uses ';' to separate two clusters (e.g. 'a:2181;b:2181') and either (a) the bundled zookeeper.jar lacks the reflectively-accessed fields 'cnxn'/'hostProvider'/'serverAddresses' (version drift), or (b) the second cluster string is unparseable by ConnectStringParser.
Common situations: Upgrading zookeeper client jar changed ClientCnxn internals so ReflectionUtils.findField returns a field whose value shape differs; using a multi-region ZK failover config where the secondary cluster string is malformed; running a shaded/relocated zookeeper jar.
Related errors
- zk client has already been started
- Unable to connect to {}
- No such method: '{}' @ {}
- Cannot invoke method: '{}' @ {}
- Invoke method failed: '{}' @ {}
AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14).
Data as JSON: /api/errors/4f2ba85a739fc558.
Report an issue: GitHub.