apache/pulsar · error · IOException
${dir} directory does not have read/write privilege
Error message
${dir} directory does not have read/write privilege What it means
ensureDirectoryExistAndCanReadAndWrite finishes by verifying File.canRead() && canWrite(); if either is false it throws IOException '<abs path> directory does not have read/write privilege'. This happens when the directory exists but the process user lacks read or write permission bits (or ACL/OS policy blocks access).
Source
Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/nar/FileUtils.java:89
}
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");
}
}
if (!dir.canRead()) {
throw new IOException(dir.getAbsolutePath() + " directory does not have read privilege");
}
}
private static boolean deleteFile(final File file, final int attempts) {View on GitHub (pinned to 820761864e)
Solutions
- chown -R the directory to the user running the process, or chmod u+rwx on it.
- Restart the service under the user that owns the directory.
- Check SELinux/AppArmor audit logs and adjust policy or file context.
- For NFS, fix root-squash / export permissions.
Example fix
// shell fix // chown -R pulsar:pulsar /var/lib/pulsar/nar && chmod -R u+rwX /var/lib/pulsar/nar
Defensive patterns
Strategy: try-catch
Validate before calling
if (dir.exists() && !(dir.canRead() && dir.canWrite())) {
throw new IllegalStateException("Insufficient permissions on " + dir
+ ": read=" + dir.canRead() + " write=" + dir.canWrite());
} Try / catch
try {
FileUtils.ensureDirectoryExistAndCanReadAndWrite(dir);
} catch (IOException e) {
if (e.getMessage().contains("read/write privilege")) {
log.error("Fix ownership: chown -R {}:{} {}", serviceUser, serviceGroup, dir);
}
throw e;
} Prevention
- Use a single dedicated service user and chown all data dirs to it
- Check umask and provisioner default modes for created directories
- Audit SELinux/AppArmor policies when running on hardened hosts
When it happens
Trigger: The directory (existing or freshly created by a different user) has mode bits denying read or write to the process user, e.g. a root-created directory with mode 700 encountered by a non-root broker process.
Common situations: A previous run as root created the NAR/cache directory; shared NFS mounts exporting root-squashed permissions; hardening policies (SELinux) denying writes; umask producing restrictive modes.
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
- ${dir} is not a directory
- ${dir} could not be created
- ${dir} directory does not have read privilege
- Cannot create ${parentDirectory}
- Failed to create parent dirs for ${path}
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/52cc31d3f9539e4d.
Report an issue: GitHub.