{"record":{"id":"157ac6322e88eaaf","repo":"apache/pulsar","slug":"cannot-create-narextractiontempdirectory","errorCode":null,"errorMessage":"Cannot create ${narExtractionTempDirectory}","messagePattern":"Cannot create (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"pulsar-common/src/main/java/org/apache/pulsar/common/nar/NarUnpacker.java","lineNumber":95,"sourceCode":"        }\n        String checksum = Base64.getUrlEncoder().withoutPadding().encodeToString(FileUtils.calculateSha256sum(nar));\n        // ensure that one process can extract the files\n        File lockFile = new File(parentDirectory, \".\" + checksum + \".lock\");\n        // prevent OverlappingFileLockException by ensuring that one thread tries to create a lock in this JVM\n        Object localLock = CURRENT_JVM_FILE_LOCKS.computeIfAbsent(lockFile.getAbsolutePath(), key -> new Object());\n        synchronized (localLock) {\n            // create file lock that ensures that other processes\n            // using the same lock file don't execute concurrently\n            try (FileChannel channel = new RandomAccessFile(lockFile, \"rw\").getChannel();\n                 FileLock lock = channel.lock()) {\n                File narWorkingDirectory = new File(parentDirectory, checksum);\n                if (!narWorkingDirectory.exists()) {\n                    File narExtractionTempDirectory = new File(parentDirectory, checksum + \".tmp\");\n                    if (narExtractionTempDirectory.exists()) {\n                        FileUtils.deleteFile(narExtractionTempDirectory, true);\n                    }\n                    if (!narExtractionTempDirectory.mkdir()) {\n                        throw new IOException(\"Cannot create \" + narExtractionTempDirectory);\n                    }\n                    try {\n                        log.info().attr(\"nar\", nar).attr(\"destination\", narExtractionTempDirectory).log(\"Extracting\");\n                        if (extractCallback != null) {\n                            extractCallback.run();\n                        }\n                        unpack(nar, narExtractionTempDirectory);\n                    } catch (IOException e) {\n                        log.error()\n                                .attr(\"directory\", narExtractionTempDirectory)\n                                .exception(e)\n                                .log(\"There was a problem extracting the nar file. Deleting to clean up state.\");\n                        try {\n                            FileUtils.deleteFile(narExtractionTempDirectory, true);\n                        } catch (IOException e2) {\n                            log.error()\n                                    .attr(\"directory\", narExtractionTempDirectory)\n                                    .exception(e2)","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-common/src/main/java/org/apache/pulsar/common/nar/NarUnpacker.java#L77-L113","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before (failing env)\nProcessBuilder pb = ...; // runs with pulsar.nar.extraction.path=/pulsar/nar owned by root\n// after\nFiles.createDirectories(Paths.get(\"/pulsar/nar\"));\nFiles.setPosixFilePermissions(Paths.get(\"/pulsar/nar\"), PosixFilePermissions.fromString(\"rwxr-xr-x\"));","handlingStrategy":"validation","validationCode":"File dir = new File(narExtractionPath);\nif (!dir.isDirectory() || !dir.canWrite()) {\n    throw new IllegalStateException(\"NAR extraction dir missing or not writable: \" + dir);\n}\nFile tmp = new File(dir, checksum + \".tmp\");\nif (tmp.exists() && !tmp.isDirectory()) tmp.delete();","typeGuard":"static boolean canCreateIn(File dir) {\n    return dir.isDirectory() && dir.canWrite();\n}","tryCatchPattern":"try {\n    Path unpacked = NarUnpacker.unpackNar(narFile, extractionDir);\n} catch (IOException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Cannot create\")) {\n        // fix permissions/space for extraction dir, then retry\n    }\n    throw new UncheckedIOException(e);\n}","preventionTips":["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."],"tags":["filesystem","io","nar"],"backgroundTag":"directory-creation-failed","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}