{"record":{"id":"8c7d788be898ca7e","repo":"opendataloader-project/opendataloader-pdf","slug":"cannot-use-the-temporary-directory-pdf-proce","errorCode":null,"errorMessage":"Cannot use the temporary directory '{}'. PDF processing needs it to read font metrics and decode content streams. Point java.io.tmpdir or the TMPDIR environment variable at a writable directory, or grant write access to this one.","messagePattern":"Cannot use the temporary directory '(.+?)'\\. PDF processing needs it to read font metrics and decode content streams\\. Point java\\.io\\.tmpdir or the TMPDIR environment variable at a writable directory, or grant write access to this one\\.","errorType":"exception","errorClass":"TempDirectoryNotWritableException","httpStatus":null,"severity":"error","filePath":"java/opendataloader-pdf-core/src/main/java/org/opendataloader/pdf/processors/DocumentProcessor.java","lineNumber":742,"sourceCode":"     *         cannot be written to\n     */\n    private static void validateTempDirWritable() throws TempDirectoryNotWritableException {\n        String tempDir = System.getProperty(\"java.io.tmpdir\");\n        try {\n            // Resolve java.io.tmpdir explicitly rather than calling the no-arg\n            // Files.createTempFile: that one resolves the directory once when the\n            // JVM starts, so it would ignore a -Djava.io.tmpdir override applied\n            // later and probe a different directory than veraPDF ends up using.\n            // RuntimeException covers InvalidPathException from a malformed override.\n            Path probe = Files.createTempFile(Path.of(tempDir), \"opendataloader-\", \".probe\");\n            // Deleting is part of what is being verified, not just cleanup: veraPDF\n            // removes its spill files, so a directory that allows creation but\n            // refuses deletion (a sticky bit the process does not own, say) would\n            // accumulate one file per stream. Failing here also keeps the probe\n            // itself from leaking.\n            Files.delete(probe);\n        } catch (IOException | RuntimeException e) {\n            throw new TempDirectoryNotWritableException(\n                \"Cannot use the temporary directory '\" + tempDir + \"'.\"\n                + \" PDF processing needs it to read font metrics and decode content streams.\"\n                + \" Point java.io.tmpdir or the TMPDIR environment variable at a writable\"\n                + \" directory, or grant write access to this one.\", e);\n        }\n    }\n\n    /**\n     * Path.getFileName() returns null for filesystem roots (e.g. {@code C:\\}).\n     * Fall back to the original input string in that case so the user-facing\n     * error message is never empty.\n     */\n    private static String displayName(String pdfName) {\n        Path fileName = Path.of(pdfName).getFileName();\n        return fileName != null ? fileName.toString() : pdfName;\n    }\n\n    private static int indexOfBytes(byte[] haystack, byte[] needle) {","sourceCodeStart":724,"sourceCodeEnd":760,"githubUrl":"https://github.com/opendataloader-project/opendataloader-pdf/blob/a7789b8e77dd05e2b8659eb3ea12fc458f80bfb8/java/opendataloader-pdf-core/src/main/java/org/opendataloader/pdf/processors/DocumentProcessor.java#L724-L760","documentation":"TempDirectoryNotWritableException (IOException subtype) thrown by validateTempDirWritable, which runs per-file before processing. It probes the JVM temp dir by creating AND deleting a file (Files.createTempFile + Files.delete), because veraPDF spills Standard-14 font metrics, embedded font programs, CMaps, and decoded content streams to disk and then deletes them — a dir that allows creation but blocks deletion would leak one file per stream. The check prevents a silent failure mode where veraPDF logs the I/O error at FINE, swallows it, and processing 'succeeds' (exit 0) while dropping most text or throwing an unrelated NPE deep inside.","triggerScenarios":"validateTempDirWritable is called at the start of updateStaticContainers/extractContents: Files.createTempFile(Path.of(tempDir), ...) or the subsequent Files.delete(probe) throws IOException (permission denied, no space, read-only mount) or RuntimeException (InvalidPathException from a malformed -Djava.io.tmpdir value).","commonSituations":"Container/image with a read-only or nodev /tmp. A malformed -Djava.io.tmpdir=/bad:|path override. TMPDIR env var pointing at a deleted/unwritable dir. Disk full. A sticky-bit /tmp the process does not own (allows create, blocks delete). Read-only root filesystem in a hardened pod.","solutions":["Point java.io.tmpdir (or TMPDIR) at a known-writable directory: run with -Djava.io.tmpdir=/var/tmp/odl or export TMPDIR=/var/tmp/odl after creating it.","Grant write+delete permission on the existing temp dir to the running user (chmod/chown), or remove the sticky-bit ownership mismatch.","Freeze disk space: check df -h on the temp dir's mount and clear space if full.","In containers, mount an emptyDir/writable volume at /tmp or set TMPDIR to a writable emptyDir."],"exampleFix":"# before: container runs with read-only /tmp\n$ odl-pdf doc.pdf\n-> TempDirectoryNotWritableException: Cannot use the temporary directory '/tmp'...\n# after: override to a writable dir\n$ mkdir -p /var/tmp/odl && TMPDIR=/var/tmp/odl odl-pdf doc.pdf","handlingStrategy":"validation","validationCode":"// Probe the temp dir yourself before processing, mirroring the library's check:\nPath tmp = Path.of(System.getProperty(\"java.io.tmpdir\"));\nPath probe = Files.createTempFile(tmp, \"pre-\", \".probe\");\nFiles.delete(probe); // must also succeed\n","typeGuard":"static boolean isTempDirProblem(IOException e) {\n    return e instanceof TempDirectoryNotWritableException;\n}","tryCatchPattern":"try {\n    DocumentProcessor.extractContents(pdfName, config);\n} catch (TempDirectoryNotWritableException e) {\n    // Environment issue, not a bad file — fix the dir, not the input.\n    String tmp = System.getProperty(\"java.io.tmpdir\");\n    log.error(\"Temp dir {} not writable; set -Djava.io.tmpdir or TMPDIR\", tmp, e);\n    throw new RuntimeException(\"Fix java.io.tmpdir then retry\", e);\n}","preventionTips":["Set -Djava.io.tmpdir (or TMPDIR) to a known-writable dir at JVM startup in containers.","Mount a writable volume at /tmp in container images.","Do NOT cache a successful probe result — java.io.tmpdir is mutable and the dir can be remounted read-only mid-process (the library re-probes per file on purpose)."],"tags":["environment","temp-dir","permissions","container","verapdf","ioexception"],"backgroundTag":null,"analyzedSha":"a7789b8e77dd05e2b8659eb3ea12fc458f80bfb8","analyzedAt":"2026-08-14T05:22:03.953Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}