{"record":{"id":"466c23e4a7898ebb","repo":"alibaba/canal","slug":"period-must-be-positive-given-period-466c23","errorCode":null,"errorMessage":"period must be positive, given: {period}","messagePattern":"period must be positive, given: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"parse/src/main/java/com/alibaba/otter/canal/parse/index/PeriodMixedLogPositionManager.java","lineNumber":47,"sourceCode":"    private long                        period;\n    private Set<String>                 persistTasks;\n\n    @SuppressWarnings(\"serial\")\n    private final LogPosition           nullPosition = new LogPosition() {\n                                                     };\n\n    public PeriodMixedLogPositionManager(MemoryLogPositionManager memoryLogPositionManager,\n                                         ZooKeeperLogPositionManager zooKeeperLogPositionManager, long period){\n        if (memoryLogPositionManager == null) {\n            throw new NullPointerException(\"null memoryLogPositionManager\");\n        }\n\n        if (zooKeeperLogPositionManager == null) {\n            throw new NullPointerException(\"null zooKeeperLogPositionManager\");\n        }\n\n        if (period <= 0) {\n            throw new IllegalArgumentException(\"period must be positive, given: \" + period);\n        }\n\n        this.memoryLogPositionManager = memoryLogPositionManager;\n        this.zooKeeperLogPositionManager = zooKeeperLogPositionManager;\n        this.period = period;\n        this.persistTasks = Collections.synchronizedSet(new HashSet<>());\n        this.executorService = Executors.newScheduledThreadPool(1);\n    }\n\n    @Override\n    public void stop() {\n        super.stop();\n\n        if (zooKeeperLogPositionManager.isStart()) {\n            zooKeeperLogPositionManager.stop();\n        }\n\n        if (memoryLogPositionManager.isStart()) {","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/alibaba/canal/blob/87be50e87686a3e8af08c368d0e1ffd1f59eb04a/parse/src/main/java/com/alibaba/otter/canal/parse/index/PeriodMixedLogPositionManager.java#L29-L65","documentation":"PeriodMixedLogPositionManager runs a scheduled executor every `period` milliseconds to push in-memory positions to ZooKeeper. A period of zero or less would disable or break the scheduler, so the constructor throws IllegalArgumentException.","triggerScenarios":"Constructing PeriodMixedLogPositionManager with period <= 0. Occurs when the flush interval property is unset (defaults to 0), mistyped, or the user set it to 0 intending to disable flushing.","commonSituations":"`canal.zk.flush.interval` omitted or set to 0; units confusion (seconds vs milliseconds); config placeholder that resolved to empty.","solutions":["Set the period to a positive millisecond value (e.g. 1000) in the instance/canal config.","When building manually, pass a checked-positive long for the period argument.","Verify the property key name matches what the config loader reads."],"exampleFix":"// before\nnew PeriodMixedLogPositionManager(memMgr, zkMgr, 0);\n\n// after\nlong period = 1000; // ms\nif (period <= 0) throw new IllegalArgumentException(\"period must be > 0\");\nnew PeriodMixedLogPositionManager(memMgr, zkMgr, period);","handlingStrategy":"validation","validationCode":"if (period <= 0) throw new IllegalArgumentException(\"period must be > 0: \" + period);\nnew PeriodMixedLogPositionManager(memMgr, zkMgr, period);","typeGuard":"boolean isPositivePeriod(long p) { return p > 0; }","tryCatchPattern":null,"preventionTips":["Give the zk flush interval a positive default in config.","Document that the unit is milliseconds."],"tags":["canal","log-position-manager","argument-validation","scheduler","configuration"],"backgroundTag":null,"analyzedSha":"87be50e87686a3e8af08c368d0e1ffd1f59eb04a","analyzedAt":"2026-08-14T04:30:11.918Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}