apache/pulsar · error · IOException
Cannot create ${narExtractionTempDirectory}
Error message
Cannot create ${narExtractionTempDirectory} What it means
NarUnpacker unpacks a NAR bundle into a temp directory named '<sha-checksum>.tmp' inside the NAR extraction parent directory before atomically renaming it. If File.mkdir() cannot create that temp directory, an IOException('Cannot create <path>') is thrown. mkdir() fails when the parent directory does not exist, is not writable, or a filesystem error (e.g. permissions, disk full, name collision as a non-directory) prevents creation.
Source
Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/nar/NarUnpacker.java:95
}
String checksum = Base64.getUrlEncoder().withoutPadding().encodeToString(FileUtils.calculateSha256sum(nar));
// ensure that one process can extract the files
File lockFile = new File(parentDirectory, "." + checksum + ".lock");
// prevent OverlappingFileLockException by ensuring that one thread tries to create a lock in this JVM
Object localLock = CURRENT_JVM_FILE_LOCKS.computeIfAbsent(lockFile.getAbsolutePath(), key -> new Object());
synchronized (localLock) {
// create file lock that ensures that other processes
// using the same lock file don't execute concurrently
try (FileChannel channel = new RandomAccessFile(lockFile, "rw").getChannel();
FileLock lock = channel.lock()) {
File narWorkingDirectory = new File(parentDirectory, checksum);
if (!narWorkingDirectory.exists()) {
File narExtractionTempDirectory = new File(parentDirectory, checksum + ".tmp");
if (narExtractionTempDirectory.exists()) {
FileUtils.deleteFile(narExtractionTempDirectory, true);
}
if (!narExtractionTempDirectory.mkdir()) {
throw new IOException("Cannot create " + narExtractionTempDirectory);
}
try {
log.info().attr("nar", nar).attr("destination", narExtractionTempDirectory).log("Extracting");
if (extractCallback != null) {
extractCallback.run();
}
unpack(nar, narExtractionTempDirectory);
} catch (IOException e) {
log.error()
.attr("directory", narExtractionTempDirectory)
.exception(e)
.log("There was a problem extracting the nar file. Deleting to clean up state.");
try {
FileUtils.deleteFile(narExtractionTempDirectory, true);
} catch (IOException e2) {
log.error()
.attr("directory", narExtractionTempDirectory)
.exception(e2)View on GitHub (pinned to 820761864e)
Solutions
- Verify the NAR extraction directory (pulsar.nar.extraction.path or java.io.tmpdir based) exists and is writable by the process user; create it with mkdir -p and chown if needed.
- Check filesystem free space and mount flags (not read-only, not full).
- Delete any stale '<checksum>.tmp' files or directories in the parent directory and restart.
- Run the process under a user that owns or can write the extraction directory; on containers mount a writable volume at the extraction path.
- Catch the IOException in the caller and retry after correcting the environment; unpackNar uses per-checksum file locks so concurrent runs are safe once the directory is writable.
Example fix
// before (failing env)
ProcessBuilder pb = ...; // runs with pulsar.nar.extraction.path=/pulsar/nar owned by root
// after
Files.createDirectories(Paths.get("/pulsar/nar"));
Files.setPosixFilePermissions(Paths.get("/pulsar/nar"), PosixFilePermissions.fromString("rwxr-xr-x")); Defensive patterns
Strategy: validation
Validate before calling
File dir = new File(narExtractionPath);
if (!dir.isDirectory() || !dir.canWrite()) {
throw new IllegalStateException("NAR extraction dir missing or not writable: " + dir);
}
File tmp = new File(dir, checksum + ".tmp");
if (tmp.exists() && !tmp.isDirectory()) tmp.delete(); Type guard
static boolean canCreateIn(File dir) {
return dir.isDirectory() && dir.canWrite();
} Try / catch
try {
Path unpacked = NarUnpacker.unpackNar(narFile, extractionDir);
} catch (IOException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Cannot create")) {
// fix permissions/space for extraction dir, then retry
}
throw new UncheckedIOException(e);
} Prevention
- Mount a writable, adequately sized volume at the NAR extraction path in containers.
- Ensure the process user owns the extraction directory; avoid running first as root then as a normal user.
- Monitor free disk space on the extraction volume.
- Clean stale '<checksum>.tmp' leftovers after crashes.
When it happens
Trigger: Calling NarUnpacker.unpackNar(...) when the parent extraction directory was deleted or is read-only (e.g. running as a non-root user against a root-owned temp dir, read-only container filesystem, or disk-full), or a stale '<checksum>.tmp' path exists as a regular file that could not be cleaned.
Common situations: Kubernetes/container deployments with a read-only or tiny emptyDir for the nar extraction path; permission changes after running the broker once as root; leftover stale .tmp entries from a crashed previous run.
Related errors
- ${dir} is not a directory
- Cannot create ${parentDirectory}
- Failed to load the additional servlet for name `${servletNam
- Failed to read decryption key from ${keyUri}
- ${dir} could not be created
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/157ac6322e88eaaf.
Report an issue: GitHub.