apache/pulsar · error · RuntimeException

Failed to create parent dirs for ${path}

Error message

Failed to create parent dirs for ${path}

What it means

getPath creates parent directories for the requested file if they do not exist; when File.mkdirs() returns false (cannot create the directories), a RuntimeException is thrown naming the path. This typically reflects a filesystem-level problem: permissions, read-only volume, or the parent being an existing regular file.

Source

Thrown at pulsar-package-management/filesystem-storage/src/main/java/org/apache/pulsar/packages/management/storage/filesystem/FileSystemPackagesStorage.java:72

        if (storagePath != null) {
            this.storagePath = new File(storagePath);
        } else {
            this.storagePath = new File(DEFAULT_STORAGE_PATH);
        }
    }

    private File getPath(String path) throws IOException {
        // Normalize the path to remove any redundant path elements
        File f = Paths.get(storagePath.toString(), path).normalize().toFile();

        // Ensure the normalized path is still within the storagePath
        if (!f.getAbsolutePath().startsWith(storagePath.getAbsolutePath())) {
            throw new IOException("Invalid path: " + path);
        }

        if (!f.getParentFile().exists()) {
            if (!f.getParentFile().mkdirs()) {
                throw new RuntimeException("Failed to create parent dirs for " + path);
            }
        }
        return f;
    }

    @Override
    public void initialize() {
        if (!storagePath.exists()) {
            if (!storagePath.mkdirs()) {
                throw new RuntimeException("Failed to create base storage directory at " + storagePath);
            }
        }

        log.info().attr("storagePath", storagePath).log("Packages management filesystem storage initialized");
    }

    @Override
    public CompletableFuture<Void> writeAsync(String path, InputStream inputStream) {

View on GitHub (pinned to 820761864e)

Solutions

  1. Check OS permissions on the storage directory and the broker process user; chown/chmod so the process can write.
  2. Ensure no regular file exists at the parent path that should be a directory; remove or rename it.
  3. Verify the volume is writable (not read-only) and has free space/inodes.
  4. Pre-create the directory hierarchy manually, then retry the operation.

Example fix

# before: permission denied -> RuntimeException
sudo chown -R pulsar:pulsar /data/pulsar/packages
# after: storage writable, getPath can mkdirs successfully
Defensive patterns

Strategy: validation

Validate before calling

java.io.File parent = java.nio.file.Paths.get(storageRoot, path).normalize().toFile().getParentFile();
boolean creatable = parent.exists() || (parent.canWrite() || parent.getParentFile().canWrite());

Try / catch

try {
    storage.readAsync(path).get();
} catch (java.util.concurrent.ExecutionException e) {
    if (e.getCause() instanceof RuntimeException && e.getCause().getMessage().startsWith("Failed to create parent dirs")) {
        log.error("Storage dir unwritable for {}: fix permissions/mount", path, e.getCause());
    }
    throw e;
}

Prevention

When it happens

Trigger: Any storage operation (read/write/delete/list/exists) whose target file's parent directory does not exist and cannot be created: storagePath on a read-only mount, insufficient OS permissions, or a file already occupying the parent path.

Common situations: Running the broker as a user without write access to the storage directory; disk mounted read-only after failure; leftover file where a directory was expected; full disk or quota exhaustion.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/80773e7b32a0548c. Report an issue: GitHub.