{"record":{"id":"f0ae5da7b2190d71","repo":"alibaba/canal","slug":"null-datadir","errorCode":null,"errorMessage":"null dataDir","messagePattern":"null dataDir","errorType":"validation","errorClass":"NullPointerException","httpStatus":null,"severity":"error","filePath":"parse/src/main/java/com/alibaba/otter/canal/parse/index/FileMixedLogPositionManager.java","lineNumber":58,"sourceCode":"\n    private File                     dataDir;\n\n    private Map<String, File>        dataFileCaches;\n\n    private ScheduledExecutorService executorService;\n\n    @SuppressWarnings(\"serial\")\n    private final LogPosition        nullPosition = new LogPosition() {\n                                                  };\n\n    private MemoryLogPositionManager memoryLogPositionManager;\n\n    private long                     period;\n    private Set<String>              persistTasks;\n\n    public FileMixedLogPositionManager(File dataDir, long period, MemoryLogPositionManager memoryLogPositionManager){\n        if (dataDir == null) {\n            throw new NullPointerException(\"null dataDir\");\n        }\n        if (period <= 0) {\n            throw new IllegalArgumentException(\"period must be positive, given: \" + period);\n        }\n        if (memoryLogPositionManager == null) {\n            throw new NullPointerException(\"null memoryLogPositionManager\");\n        }\n        this.dataDir = dataDir;\n        this.period = period;\n        this.memoryLogPositionManager = memoryLogPositionManager;\n\n        this.dataFileCaches = MigrateMap.makeComputingMap(this::getDataFile);\n\n        this.executorService = Executors.newScheduledThreadPool(1);\n        this.persistTasks = Collections.synchronizedSet(new HashSet<>());\n    }\n\n    @Override","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/alibaba/canal/blob/87be50e87686a3e8af08c368d0e1ffd1f59eb04a/parse/src/main/java/com/alibaba/otter/canal/parse/index/FileMixedLogPositionManager.java#L40-L76","documentation":"FileMixedLogPositionManager caches positions in memory and periodically flushes them to files under a data directory. The constructor rejects a null dataDir with NullPointerException because there is no filesystem location to persist to. The directory is also created and permission-checked later in start(), but the null guard fires first at construction.","triggerScenarios":"Calling `new FileMixedLogPositionManager(dataDir, period, memoryLogPositionManager)` with dataDir == null. Typically the `canal.instance.position.dataDir` / `canal.dataDir` property is unset or resolves to a null File.","commonSituations":"The deployer's `canal.conf` or instance properties omit the data directory; running in a container where the configured data path env var is missing; a refactor that stopped injecting the dataDir File bean.","solutions":["Set the data directory property (e.g. canal.dataDir / canal.instance.position.dataDir) to a non-null path in canal.conf or the instance properties.","If constructing manually, pass `new File(\"/your/canal/data\")` and verify the File is non-null before calling the constructor.","Confirm the config value is not blank or referencing an undefined placeholder."],"exampleFix":"// before\nnew FileMixedLogPositionManager(null, period, memoryMgr);\n\n// after\nFile dir = new File(Objects.requireNonNull(dataDirPath, \"dataDirPath\"));\nnew FileMixedLogPositionManager(dir, period, memoryMgr);","handlingStrategy":"validation","validationCode":"File dir = new File(Objects.requireNonNull(dataDirPath, \"dataDirPath\"));\nnew FileMixedLogPositionManager(dir, period, memoryMgr);","typeGuard":"boolean isValidDataDir(File f) { return f != null; }","tryCatchPattern":null,"preventionTips":["Bind the data directory to a required config key with a non-null default.","Assert the resolved File is non-null at application startup, before any manager is built.","Log the resolved dataDir path during bootstrap to catch missing config early."],"tags":["canal","log-position-manager","null-check","filesystem","configuration"],"backgroundTag":null,"analyzedSha":"87be50e87686a3e8af08c368d0e1ffd1f59eb04a","analyzedAt":"2026-08-14T04:30:11.918Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}