apache/pulsar · error · IOException

${dir} is not a directory

Error message

${dir} is not a directory

What it means

FileUtils.ensureDirectoryExistAndCanReadAndWrite(dir) prepares a directory that must exist and be readable/writable. If the File exists but is a regular file (or other non-directory), it throws IOException '<abs path> is not a directory' because a file occupies the path where a directory is required. It will happily create the directory if missing, but never overwrite an existing file.

Source

Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/nar/FileUtils.java:81

            final MessageDigest digest = MessageDigest.getInstance("SHA-256");

            final byte[] buffer = new byte[8192];
            int read = inputStream.read(buffer);

            while (read > -1) {
                digest.update(buffer, 0, read);
                read = inputStream.read(buffer);
            }

            return digest.digest();
        } catch (NoSuchAlgorithmException nsae) {
            throw new IllegalArgumentException(nsae);
        }
    }

    public static void ensureDirectoryExistAndCanReadAndWrite(final File dir) throws IOException {
        if (dir.exists() && !dir.isDirectory()) {
            throw new IOException(dir.getAbsolutePath() + " is not a directory");
        } else if (!dir.exists()) {
            final boolean made = dir.mkdirs();
            if (!made) {
                throw new IOException(dir.getAbsolutePath() + " could not be created");
            }
        }
        if (!(dir.canRead() && dir.canWrite())) {
            throw new IOException(dir.getAbsolutePath() + " directory does not have read/write privilege");
        }
    }

    public static void ensureDirectoryExistAndCanRead(final File dir) throws IOException {
        if (dir.exists() && !dir.isDirectory()) {
            throw new IOException(dir.getAbsolutePath() + " is not a directory");
        } else if (!dir.exists()) {
            final boolean made = dir.mkdirs();
            if (!made) {
                throw new IOException(dir.getAbsolutePath() + " could not be created");

View on GitHub (pinned to 820761864e)

Solutions

  1. Inspect the path (ls -la) and remove or rename the file occupying it, then retry so the code can mkdirs.
  2. Fix the configuration property pointing at this path so it names a dedicated directory.
  3. In containers/orchestrators, mount a volume/directory, not a single file, at that path.

Example fix

// before
File dir = new File(config.getNarDir()); // path is a leftover file
FileUtils.ensureDirectoryExistAndCanReadAndWrite(dir);
// after
File dir = new File(config.getNarDir());
if (dir.exists() && !dir.isDirectory()) {
    dir.delete(); // or move it aside
}
FileUtils.ensureDirectoryExistAndCanReadAndWrite(dir);
Defensive patterns

Strategy: validation

Validate before calling

File dir = new File(path);
if (dir.exists() && !dir.isDirectory()) {
    throw new IllegalStateException("Path is a file, expected directory: " + path);
}

Try / catch

try {
    FileUtils.ensureDirectoryExistAndCanReadAndWrite(dir);
} catch (IOException e) {
    // e.getMessage() ends with 'is not a directory' -> move file aside or fail config
    throw new IllegalStateException("Fix path " + dir + ": " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: Passing a File whose path already exists as a regular file (or symlink to a file) to ensureDirectoryExistAndCanReadAndWrite.

Common situations: NAR extraction/cache directories (e.g. the narExtractBundleDirectory config) pointing at a path where a stale file was created earlier, a previous misconfiguration wrote a file at the expected directory path, or a container mount maps a file instead of a directory.

Related errors


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