alibaba/canal · error · CanalMetaManagerException

dir[{path}] can not read/write

Error message

dir[{path}] can not read/write

What it means

During start(), FileMixedLogPositionManager ensures its data directory exists (creating it if needed) and then verifies it is both readable and writable. If either permission is missing it throws CanalMetaManagerException with the offending path. This is a runtime/environment check, not a constructor argument check.

Source

Thrown at parse/src/main/java/com/alibaba/otter/canal/parse/index/FileMixedLogPositionManager.java:89

        this.executorService = Executors.newScheduledThreadPool(1);
        this.persistTasks = Collections.synchronizedSet(new HashSet<>());
    }

    @Override
    public void start() {
        super.start();

        if (!dataDir.exists()) {
            try {
                FileUtils.forceMkdir(dataDir);
            } catch (IOException e) {
                throw new CanalMetaManagerException(e);
            }
        }

        if (!dataDir.canRead() || !dataDir.canWrite()) {
            throw new CanalMetaManagerException("dir[" + dataDir.getPath() + "] can not read/write");
        }

        if (!memoryLogPositionManager.isStart()) {
            memoryLogPositionManager.start();
        }

        // 启动定时工作任务
        executorService.scheduleAtFixedRate(() -> {
            List<String> tasks = new ArrayList<>(persistTasks);
            for (String destination : tasks) {
                try {
                    // 定时将内存中的最新值刷到file中,多次变更只刷一次
                    flushDataToFile(destination);
                    persistTasks.remove(destination);
                } catch (Throwable e) {
                    // ignore
                    logger.error("period update" + destination + " curosr failed!", e);
                }

View on GitHub (pinned to 87be50e876)

Solutions

  1. Check ownership/permissions of the data directory and grant the canal process read+write (e.g. `chown` / `chmod 750` on the data dir).
  2. Verify the dataDir path is a directory, not a file, and lives on a writable filesystem.
  3. When running in a container, ensure the volume is mounted with the correct UID/GID matching the canal process.

Example fix

// before
// dataDir = /data/canal owned by root, canal runs as 'canal' user -> start() throws

// after
// sudo chown -R canal:canal /data/canal && sudo chmod 750 /data/canal
manager.start();
Defensive patterns

Strategy: validation

Validate before calling

File dir = new File(Objects.requireNonNull(dataDirPath));
if (!dir.exists() && !dir.mkdirs()) throw new IOException("cannot create " + dir);
if (!dir.canRead() || !dir.canWrite()) {
    throw new IllegalStateException("dataDir not read/writeable: " + dir);
}
manager.start();

Type guard

boolean isReadWriteable(File f) {
    return f != null && f.isDirectory() && f.canRead() && f.canWrite();
}

Try / catch

try {
    manager.start();
} catch (CanalMetaManagerException e) {
    // log the path, then surface a clear permission/ownership hint
    logger.error("Cannot access dataDir; check permissions", e);
    throw e;
}

Prevention

When it happens

Trigger: Calling start() when the dataDir exists (or was just created) but the canal process lacks read or write permission on it. Also triggered by a path that is a regular file rather than a directory, or an SELinux/AppArmor denial.

Common situations: Running the canal process as a different user than the directory owner; the data dir lives on a read-only mount; Docker volume mounted with wrong UID; directory owned by root but canal runs as non-root.

Related errors


AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14). Data as JSON: /api/errors/b2265df6a3f1e4ea. Report an issue: GitHub.