{"record":{"id":"f1e7f259b04e79a7","repo":"alibaba/canal","slug":"unable-to-connect-to","errorCode":null,"errorMessage":"Unable to connect to {}","messagePattern":"Unable to connect to (.+?)","errorType":"exception","errorClass":"ZkException","httpStatus":null,"severity":"error","filePath":"common/src/main/java/com/alibaba/otter/canal/common/zookeeper/ZooKeeperx.java","lineNumber":76,"sourceCode":"        ReflectionUtils.makeAccessible(zookeeperLockField);\n        ReflectionUtils.makeAccessible(zookeeperFiled);\n        Lock _zookeeperLock = (ReentrantLock) ReflectionUtils.getField(zookeeperLockField, this);\n        ZooKeeper _zk = (ZooKeeper) ReflectionUtils.getField(zookeeperFiled, this);\n\n        _zookeeperLock.lock();\n        try {\n            if (_zk != null) {\n                throw new IllegalStateException(\"zk client has already been started\");\n            }\n            String zkServers = _serversList.get(0);\n\n            try {\n                logger.debug(\"Creating new ZookKeeper instance to connect to \" + zkServers + \".\");\n                _zk = new ZooKeeper(zkServers, _sessionTimeOut, watcher);\n                configMutliCluster(_zk);\n                ReflectionUtils.setField(zookeeperFiled, this, _zk);\n            } catch (IOException e) {\n                throw new ZkException(\"Unable to connect to \" + zkServers, e);\n            }\n        } finally {\n            _zookeeperLock.unlock();\n        }\n    }\n\n    // ===============================\n\n    public void configMutliCluster(ZooKeeper zk) {\n        if (_serversList.size() == 1) {\n            return;\n        }\n        String cluster1 = _serversList.get(0);\n        try {\n            if (_serversList.size() > 1) {\n                // 强制的声明accessible\n                ReflectionUtils.makeAccessible(clientCnxnField);\n                ReflectionUtils.makeAccessible(hostProviderField);","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/alibaba/canal/blob/87be50e87686a3e8af08c368d0e1ffd1f59eb04a/common/src/main/java/com/alibaba/otter/canal/common/zookeeper/ZooKeeperx.java#L58-L94","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\ncanal.zkServers = 127.0.0.2:2181   // unreachable\n// after\ncanal.zkServers = zk1.prod:2181,zk2.prod:2181,zk3.prod:2181","handlingStrategy":"retry","validationCode":"// Pre-flight check that the ZK ensemble is reachable before constructing ZooKeeperx\nboolean reachable(String host, int port, int timeoutMs) {\n    try (java.net.Socket s = new java.net.Socket()) {\n        s.connect(new java.net.InetSocketAddress(host, port), timeoutMs);\n        return true;\n    } catch (IOException e) {\n        return false;\n    }\n}\n// if (!reachable(\"zk1\", 2181, 2000)) { delay/abort startup }","typeGuard":null,"tryCatchPattern":"int attempt = 0;\nwhile (true) {\n    try {\n        zkClient.connect(watcher);\n        break;\n    } catch (org.I0Itec.zkclient.exception.ZkException e) {\n        if (e.getMessage().startsWith(\"Unable to connect\") && ++attempt < MAX_RETRIES) {\n            // backoff and retry\n        } else throw e;\n    }\n}","preventionTips":["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."],"tags":["zookeeper","network","connection","startup"],"backgroundTag":null,"analyzedSha":"87be50e87686a3e8af08c368d0e1ffd1f59eb04a","analyzedAt":"2026-08-14T04:30:11.918Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}