apache/pulsar · error · IOException

${dir} directory does not have read privilege

Error message

${dir} directory does not have read privilege

What it means

ensureDirectoryExistAndCanRead ends by checking File.canRead(); if false it throws IOException '<abs path> directory does not have read privilege'. The directory exists, but the process user lacks read permission, so its contents cannot be listed.

Source

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

                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");
            }
        }
        if (!dir.canRead()) {
            throw new IOException(dir.getAbsolutePath() + " directory does not have read privilege");
        }
    }

    private static boolean deleteFile(final File file, final int attempts) {
        if (file == null) {
            return false;
        }
        boolean isGone = false;
        try {
            if (file.exists()) {
                final int effectiveAttempts = Math.max(1, attempts);
                for (int i = 0; i < effectiveAttempts && !isGone; i++) {
                    isGone = file.delete() || !file.exists();
                    if (!isGone && (effectiveAttempts - i) > 1) {
                        FileUtils.sleepQuietly(MILLIS_BETWEEN_ATTEMPTS);
                    }
                }
                if (!isGone) {

View on GitHub (pinned to 820761864e)

Solutions

  1. chmod u+r (or o+r as appropriate) on the directory.
  2. chown the directory to the service user.
  3. Check getenforce/audit logs for SELinux denials and fix the policy or context.
  4. Verify NFS/AD uid mapping grants read access.

Example fix

// shell fix
// chmod a+rx /var/lib/pulsar/nar  # or chown pulsar:pulsar
Defensive patterns

Strategy: validation

Validate before calling

if (dir.exists() && !dir.canRead()) {
    throw new IllegalStateException("No read permission on " + dir);
}

Try / catch

try {
    FileUtils.ensureDirectoryExistAndCanRead(dir);
} catch (IOException e) {
    if (e.getMessage().contains("read privilege")) {
        log.error("Grant read: chmod a+rx {} or chown to service user", dir);
    }
    throw e;
}

Prevention

When it happens

Trigger: Directory mode denies read (e.g. 300 = write/execute only) or ACL/OS policy blocks reading for the process user.

Common situations: Directories provisioned by automation with restrictive modes, root-owned dirs read by non-root services, hardened SELinux policies, or NFS exports without read for the mapped uid.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


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