{"record":{"id":"4fa0e75d957ca2e3","repo":"alibaba/canal","slug":"null-zkclient-4fa0e7","errorCode":null,"errorMessage":"null zkClient","messagePattern":"null zkClient","errorType":"validation","errorClass":"NullPointerException","httpStatus":null,"severity":"error","filePath":"parse/src/main/java/com/alibaba/otter/canal/parse/index/ZooKeeperLogPositionManager.java","lineNumber":20,"sourceCode":"\nimport org.I0Itec.zkclient.exception.ZkNoNodeException;\n\nimport com.alibaba.otter.canal.common.utils.JsonUtils;\nimport com.alibaba.otter.canal.common.zookeeper.ZkClientx;\nimport com.alibaba.otter.canal.common.zookeeper.ZookeeperPathUtils;\nimport com.alibaba.otter.canal.parse.exception.CanalParseException;\nimport com.alibaba.otter.canal.protocol.position.LogPosition;\n\n/**\n * Created by yinxiu on 17/3/17. Email: marklin.hz@gmail.com\n */\npublic class ZooKeeperLogPositionManager extends AbstractLogPositionManager {\n\n    private final ZkClientx zkClientx;\n\n    public ZooKeeperLogPositionManager(ZkClientx zkClient){\n        if (zkClient == null) {\n            throw new NullPointerException(\"null zkClient\");\n        }\n\n        this.zkClientx = zkClient;\n    }\n\n    @Override\n    public LogPosition getLatestIndexBy(String destination) {\n        String path = ZookeeperPathUtils.getParsePath(destination);\n        byte[] data = zkClientx.readData(path, true);\n        if (data == null || data.length == 0) {\n            return null;\n        }\n\n        return JsonUtils.unmarshalFromByte(data, LogPosition.class);\n    }\n\n    @Override\n    public void persistLogPosition(String destination, LogPosition logPosition) throws CanalParseException {","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/alibaba/canal/blob/87be50e87686a3e8af08c368d0e1ffd1f59eb04a/parse/src/main/java/com/alibaba/otter/canal/parse/index/ZooKeeperLogPositionManager.java#L2-L38","documentation":"ZooKeeperLogPositionManager reads and writes binlog positions directly to ZooKeeper nodes. Its only dependency is a ZkClientx; a null client throws NullPointerException at construction because there is no way to reach the store.","triggerScenarios":"Calling `new ZooKeeperLogPositionManager(zkClient)` with zkClient == null. This typically propagates upward (it also causes MixedLogPositionManager/PeriodMixed failures) when the zk client was never built.","commonSituations":"`canal.zkServers` unset; ZkClientx construction failed silently and returned null; a test environment without a ZooKeeper instance.","solutions":["Configure canal.zkServers with a reachable ZooKeeper address.","Build ZkClientx via ZkClientx.getZkClient(...) and confirm it is non-null before constructing the manager.","For tests, stand up an embedded ZooKeeper TestingServer."],"exampleFix":"// before\nnew ZooKeeperLogPositionManager(null);\n\n// after\nZkClientx zk = ZkClientx.getZkClient(zkServers);\nnew ZooKeeperLogPositionManager(Objects.requireNonNull(zk, \"zkClient\"));","handlingStrategy":"validation","validationCode":"ZkClientx zk = Objects.requireNonNull(zkClient, \"zkClient\");\nnew ZooKeeperLogPositionManager(zk);","typeGuard":"boolean hasZkClient(ZkClientx z) { return z != null; }","tryCatchPattern":null,"preventionTips":["Set canal.zkServers before constructing any ZooKeeper-backed manager.","For tests, use an embedded ZooKeeper TestingServer."],"tags":["canal","log-position-manager","null-check","zookeeper","configuration"],"backgroundTag":null,"analyzedSha":"87be50e87686a3e8af08c368d0e1ffd1f59eb04a","analyzedAt":"2026-08-14T04:30:11.918Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}