{"record":{"id":"d133b73c6a0c17f1","repo":"alibaba/canal","slug":"null-zkclient","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/MixedLogPositionManager.java","lineNumber":28,"sourceCode":"import 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 Memory first.\n * Asynchronous commit position info to ZK.\n */\npublic class MixedLogPositionManager extends AbstractLogPositionManager {\n\n    private final Logger                      logger = LoggerFactory.getLogger(MixedLogPositionManager.class);\n\n    private final MemoryLogPositionManager    memoryLogPositionManager;\n    private final ZooKeeperLogPositionManager zooKeeperLogPositionManager;\n\n    private final ExecutorService             executor;\n\n    public MixedLogPositionManager(ZkClientx zkClient){\n        if (zkClient == null) {\n            throw new NullPointerException(\"null zkClient\");\n        }\n\n        this.memoryLogPositionManager = new MemoryLogPositionManager();\n        this.zooKeeperLogPositionManager = new ZooKeeperLogPositionManager(zkClient);\n\n        this.executor = Executors.newFixedThreadPool(1);\n    }\n\n    @Override\n    public void start() {\n        super.start();\n\n        if (!memoryLogPositionManager.isStart()) {\n            memoryLogPositionManager.start();\n        }\n\n        if (!zooKeeperLogPositionManager.isStart()) {\n            zooKeeperLogPositionManager.start();","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/alibaba/canal/blob/87be50e87686a3e8af08c368d0e1ffd1f59eb04a/parse/src/main/java/com/alibaba/otter/canal/parse/index/MixedLogPositionManager.java#L10-L46","documentation":"MixedLogPositionManager keeps positions in memory for speed and asynchronously mirrors them to ZooKeeper for durability. It builds both delegates from a single ZkClientx, so a null zkClient is fatal and the constructor throws NullPointerException. Without the zk client the durable mirror cannot be constructed.","triggerScenarios":"Calling `new MixedLogPositionManager(zkClient)` with zkClient == null. Occurs when the zookeeper address property is empty/unset, so the ZkClientx was never built, or the builder returned null on connection failure.","commonSituations":"`canal.zkServers` is not configured; a network issue during ZkClientx construction returned null; a test that forgets to provide a zk test server (e.g. embedded ZooKeeper).","solutions":["Set canal.zkServers to a reachable ZooKeeper cluster address before constructing the manager.","Ensure ZkClientx is built and non-null (handle connection failures explicitly rather than passing null).","For tests, use an embedded ZooKeeper TestingServer and pass a real ZkClientx."],"exampleFix":"// before\nnew MixedLogPositionManager(null);\n\n// after\nZkClientx zk = ZkClientx.getZkClient(zkServers);\nnew MixedLogPositionManager(Objects.requireNonNull(zk, \"zkClient\"));","handlingStrategy":"validation","validationCode":"ZkClientx zk = Objects.requireNonNull(zkClient, \"zkClient\");\nnew MixedLogPositionManager(zk);","typeGuard":"boolean hasZkClient(ZkClientx z) { return z != null; }","tryCatchPattern":null,"preventionTips":["Always configure canal.zkServers when using a Mixed or ZooKeeper-backed manager.","For tests, use an embedded ZooKeeper TestingServer so zkClient is never null."],"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"}