{"record":{"id":"5845f25dbb060efd","repo":"junit-team/junit5","slug":"temp-directory-must-be-a-directory","errorCode":null,"errorMessage":"temp directory must be a directory","messagePattern":"temp directory must be a directory","errorType":"exception","errorClass":"PreconditionViolationException","httpStatus":null,"severity":"error","filePath":"junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TempDirectory.java","lineNumber":273,"sourceCode":"\tstatic class CloseablePath implements Store.CloseableResource, AutoCloseable {\n\n\t\tprivate final @Nullable Path dir;\n\t\tprivate final TempDirFactory factory;\n\t\tprivate final Cleanup cleanup;\n\t\tprivate final AnnotatedElementContext elementContext;\n\t\tprivate final ExtensionContext extensionContext;\n\n\t\tprivate CloseablePath(TempDirFactory factory, Cleanup cleanup, Class<?> elementType,\n\t\t\t\tAnnotatedElementContext elementContext, ExtensionContext extensionContext) throws Exception {\n\t\t\tthis.dir = factory.createTempDirectory(elementContext, extensionContext);\n\t\t\tthis.factory = factory;\n\t\t\tthis.cleanup = cleanup;\n\t\t\tthis.elementContext = elementContext;\n\t\t\tthis.extensionContext = extensionContext;\n\n\t\t\tif (this.dir == null || !Files.isDirectory(this.dir)) {\n\t\t\t\tclose();\n\t\t\t\tthrow new PreconditionViolationException(\"temp directory must be a directory\");\n\t\t\t}\n\n\t\t\tif (elementType == File.class && !this.dir.getFileSystem().equals(FileSystems.getDefault())) {\n\t\t\t\tclose();\n\t\t\t\tthrow new PreconditionViolationException(\n\t\t\t\t\t\"temp directory with non-default file system cannot be injected into \" + File.class.getName()\n\t\t\t\t\t\t\t+ \" target\");\n\t\t\t}\n\t\t}\n\n\t\tPath get() {\n\t\t\treturn requireNonNull(this.dir);\n\t\t}\n\n\t\t@Override\n\t\tpublic void close() throws IOException {\n\t\t\ttry {\n\t\t\t\tif (this.dir != null) {","sourceCodeStart":255,"sourceCodeEnd":291,"githubUrl":"https://github.com/junit-team/junit5/blob/f070c699a08b5d8393df9afd147af5c5e90bb21b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TempDirectory.java#L255-L291","documentation":"Thrown as PreconditionViolationException inside the CloseablePath constructor when factory.createTempDirectory returned null or returned a Path that is not an existing directory (Files.isDirectory is false). The constructor closes the (already half-built) CloseablePath first to avoid leaking resources, then throws.","triggerScenarios":"A custom TempDirFactory.createTempDirectory returns null or returns a path that does not exist / is a regular file. After this.dir is assigned, the precondition `this.dir == null || !Files.isDirectory(this.dir)` triggers close() then throws.","commonSituations":"Custom factory returns Paths.get(\"/some/path\") without actually creating it; factory returns null on failure instead of throwing; factory returns a path that was concurrently deleted; misbehaving factory in a library.","solutions":["Fix the custom TempDirFactory so createTempDirectory always returns a directory that exists (use Files.createDirectories(...) before returning).","Have the factory throw an exception rather than returning null when it cannot create the dir.","Switch to the default factory if you do not need custom placement."],"exampleFix":"// before\npublic Path createTempDirectory(AnnotatedElementContext ctx, ExtensionContext ec) {\n    return Path.of(\"/tmp/maybe-not-created\"); // not actually a dir\n}\n// after\npublic Path createTempDirectory(AnnotatedElementContext ctx, ExtensionContext ec) throws IOException {\n    Path p = Path.of(\"/tmp/mybase\").resolve(\"junit-\" + UUID.randomUUID());\n    Files.createDirectories(p);\n    return p;\n}","handlingStrategy":"validation","validationCode":"Path candidate = factory.createTempDirectory(ctx, ec);\nif (candidate == null || !Files.isDirectory(candidate)) {\n    throw new IllegalStateException(\"Factory returned non-directory: \" + candidate);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Custom TempDirFactory.createTempDirectory must always create and return an existing directory (use Files.createDirectories).","Have the factory throw rather than return null on failure.","Add a unit test that asserts Files.isDirectory(out) after the factory call."],"tags":["tempdir","factory","precondition","filesystem","extension"],"backgroundTag":null,"analyzedSha":"f070c699a08b5d8393df9afd147af5c5e90bb21b","analyzedAt":"2026-08-11T20:31:00.530Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}