apache/cassandra · error · RuntimeException

Unable to create directory

Error message

Unable to create directory ${logDir}

What it means

After validating the log directory location, maybeCreateProfilesLogDir attempts to create it (createDirectoriesIfNotExists). If that filesystem operation fails for any reason (permissions, read-only volume, path is a file), the original cause is discarded and a RuntimeException with the log dir path is thrown, so callers can see which directory could not be created.

Solutions

  1. Create the directory manually as the user running Cassandra and chown it appropriately (mkdir -p && chown cassandra)
  2. Fix the configured log dir path (typo, wrong mount) to a writable location
  3. Check filesystem mount flags/permissions (read-only, SELinux context) and remount or relabel
  4. Inspect the original cause in Cassandra's debug logs if present; the rethrown message omits it

Example fix

// before
async_profiler_dir: /proc/cassandra-prof
// after
sudo mkdir -p /var/log/cassandra/async-profiler && sudo chown cassandra:cassandra /var/log/cassandra/async-profiler
Defensive patterns

Strategy: try-catch

Validate before calling

Path p = Path.of(logDir);
if (!Files.isDirectory(p)) Files.createDirectories(p); // fail early with a clear cause
if (!Files.isWritable(p)) throw new AccessDeniedException(p.toString());

Try / catch

try { svc.apply(cmd, file); } catch (RuntimeException e) { if (e.getMessage().startsWith("Unable to create directory")) { Files.createDirectories(Path.of(logDir)); svc.apply(cmd, file); } else throw e; }

Prevention

When it happens

Trigger: Profiling MBean calls (instance/apply/list/fetch/purge) when the configured log dir cannot be created: parent dirs missing and uncreatable, OS permission denied, read-only filesystem, or a regular file already exists at that path.

Common situations: Non-root Cassandra user lacking write access to the configured path; Docker/Kubernetes volumes mounted read-only; SELinux/AppArmor denials; disk full or typo in the directory path.

Understand the failure class

Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/13c13d51b417571a. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/service/AsyncProfilerService.java:448

            (DatabaseDescriptor.getCDCLogLocation() != null && dir.startsWith(DatabaseDescriptor.getCDCLogLocation())) ||
            (DatabaseDescriptor.getSavedCachesLocation() != null && dir.startsWith(DatabaseDescriptor.getSavedCachesLocation())))
        {
            throw new RuntimeException("You can not store Async-Profiler results into system Cassandra directory.");
        }

        for (String location : StorageService.instance.getAllDataFileLocations())
        {
            if (dir.startsWith(location))
                throw new RuntimeException("You can not store Async-Profiler results into a data directory of Cassandra.");
        }

        try
        {
            new File(logDir).createDirectoriesIfNotExists();
        }
        catch (Throwable t)
        {
            throw new RuntimeException("Unable to create directory " + logDir);
        }
    }

    private void validateStartParameters(Map<String, String> parameters)
    {
        if (!ASYNC_PROFILER_START_PARAMS.equals(parameters.keySet()))
        {
            throw new IllegalArgumentException("Wrong parameters passed to start async profiler method. Passed parameters" +
                                               " should be: " + ASYNC_PROFILER_START_PARAMS);
        }
    }

    private void validateStopParameters(Map<String, String> parameters)
    {
        if (!ASYNC_PROFILER_STOP_PARAMS.containsAll(parameters.keySet()))
        {
            throw new IllegalArgumentException("Wrong parameters passed to stop async profiler method. Passed parameters" +
                                               " should be: " + ASYNC_PROFILER_STOP_PARAMS);

View on GitHub (pinned to 88fd0f6a0e)