apache/pulsar · critical · RuntimeException

Failed to create base storage directory at ${storagePath}

Error message

Failed to create base storage directory at ${storagePath}

What it means

At startup, FileSystemPackagesStorage.initialize() creates the configured base storage directory if it does not exist; when storagePath.mkdirs() fails, a RuntimeException naming the path is thrown, aborting initialization. The broker cannot start filesystem package storage without a usable base directory.

Source

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

        // 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) {
        try {
            File f = getPath(path);

            @Cleanup
            OutputStream os = new FileOutputStream(f);

            @Cleanup
            BufferedOutputStream bos = new BufferedOutputStream(os);
            ByteStreams.copy(inputStream, bos);

View on GitHub (pinned to 820761864e)

Solutions

  1. Check permissions on the parent of the configured storage path and grant the broker process user write access.
  2. Pre-create the storage directory manually with correct ownership, then restart.
  3. Verify the volume/mount is writable (not read-only) and the path is correct in configuration.
  4. Ensure storagePath is a directory, not an existing regular file.

Example fix

// before: path not writable
-DpackagesManagement.storage.filesystem.root=/root/only/packages
// after
-DpackagesManagement.storage.filesystem.root=/var/lib/pulsar/packages
# chown pulsar:pulsar /var/lib/pulsar/packages
Defensive patterns

Strategy: validation

Validate before calling

java.io.File root = new java.io.File(storageRoot);
if (!root.exists() && !root.getParentFile().canWrite()) {
    throw new IllegalStateException("Cannot create storage root " + storageRoot + ": parent not writable");
}
if (root.exists() && !root.isDirectory()) {
    throw new IllegalStateException(storageRoot + " exists but is not a directory");
}

Try / catch

try {
    storage.initialize();
} catch (RuntimeException e) {
    if (e.getMessage().startsWith("Failed to create base storage directory")) {
        log.error("Fix storage root permissions/mount: {}", e.getMessage());
        throw e; // non-recoverable at startup
    }
    throw e;
}

Prevention

When it happens

Trigger: initialize() with storagePath pointing to a non-existent directory that cannot be created: parent directories missing and uncreatable, permission denied, read-only filesystem, or storagePath exists as a regular file... (note: if it exists as a file, mkdirs is skipped and other operations will fail).

Common situations: Wrong packagesManagement storage path in configuration (typo, unwritable location); container running as non-root without volume permissions; Kubernetes PVC mounted read-only; parent of storagePath not existing.

Related errors


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