alibaba/canal · error · ZkException
Unable to connect to {}
Error message
Unable to connect to {} What it means
Thrown by ZooKeeperx.connect when the java.io.IOException escapes from 'new ZooKeeper(zkServers, timeout, watcher)'. It is wrapped as ZkException (an I0Itec zkclient runtime exception) carrying the connect string. The root cause is almost always network/connect-string: unreachable hosts, DNS failure, malformed connect string, or firewall dropping the 2181 port.
Source
Thrown at common/src/main/java/com/alibaba/otter/canal/common/zookeeper/ZooKeeperx.java:76
ReflectionUtils.makeAccessible(zookeeperLockField);
ReflectionUtils.makeAccessible(zookeeperFiled);
Lock _zookeeperLock = (ReentrantLock) ReflectionUtils.getField(zookeeperLockField, this);
ZooKeeper _zk = (ZooKeeper) ReflectionUtils.getField(zookeeperFiled, this);
_zookeeperLock.lock();
try {
if (_zk != null) {
throw new IllegalStateException("zk client has already been started");
}
String zkServers = _serversList.get(0);
try {
logger.debug("Creating new ZookKeeper instance to connect to " + zkServers + ".");
_zk = new ZooKeeper(zkServers, _sessionTimeOut, watcher);
configMutliCluster(_zk);
ReflectionUtils.setField(zookeeperFiled, this, _zk);
} catch (IOException e) {
throw new ZkException("Unable to connect to " + zkServers, e);
}
} finally {
_zookeeperLock.unlock();
}
}
// ===============================
public void configMutliCluster(ZooKeeper zk) {
if (_serversList.size() == 1) {
return;
}
String cluster1 = _serversList.get(0);
try {
if (_serversList.size() > 1) {
// 强制的声明accessible
ReflectionUtils.makeAccessible(clientCnxnField);
ReflectionUtils.makeAccessible(hostProviderField);View on GitHub (pinned to 87be50e876)
Solutions
- Verify the ZK ensemble is reachable: run 'echo ruok | nc <host> 2181' or 'zkCli.sh -server <servers>' from the canal host.
- Correct canal.zkServers in canal.properties to point at a live ensemble (host:port, comma-separated, ';' separates multi-cluster groups).
- Open firewall/security-group egress on port 2181 from the canal node to the ZK hosts.
- If transient, retry startup after confirming network, or enable canal-level reconnect rather than a manual double-connect.
Example fix
// before canal.zkServers = 127.0.0.2:2181 // unreachable // after canal.zkServers = zk1.prod:2181,zk2.prod:2181,zk3.prod:2181
Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight check that the ZK ensemble is reachable before constructing ZooKeeperx
boolean reachable(String host, int port, int timeoutMs) {
try (java.net.Socket s = new java.net.Socket()) {
s.connect(new java.net.InetSocketAddress(host, port), timeoutMs);
return true;
} catch (IOException e) {
return false;
}
}
// if (!reachable("zk1", 2181, 2000)) { delay/abort startup } Try / catch
int attempt = 0;
while (true) {
try {
zkClient.connect(watcher);
break;
} catch (org.I0Itec.zkclient.exception.ZkException e) {
if (e.getMessage().startsWith("Unable to connect") && ++attempt < MAX_RETRIES) {
// backoff and retry
} else throw e;
}
} Prevention
- Validate canal.zkServers resolves and is reachable at deploy time.
- Run ZK startup checks in a retry-with-backoff wrapper rather than failing the process on a transient blip.
- Keep ZK ensemble behind a stable, firewall-allowed endpoint.
When it happens
Trigger: new ZooKeeper(zkServers,...) throws IOException because no ZK ensemble member at the first cluster entry is reachable; connect string is empty/blank/unresolvable; session-timeout vs. network-partition mismatch.
Common situations: Wrong canal.zkServers value (typo, stale host); ZK ensemble down during canal startup; security group/firewall blocks port 2181; Kerberos/SASL misconfiguration causing handshake IOException; running canal in a container whose DNS cannot resolve ZK hostnames.
Related errors
- connect failure
- can't create socket!
- command : 'show binlog events limit 1' has an error!
- canal.adminUser is empty , pls check https://github.com/alib
- canal.adminPasswd is empty , pls check https://github.com/al
AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14).
Data as JSON: /api/errors/f1e7f259b04e79a7.
Report an issue: GitHub.