{"id":"dd3dfc2e19fe6789","repo":"junit-team/junit5","slug":"failed-to-create-output-directory","errorCode":null,"errorMessage":"Failed to create output directory","messagePattern":"Failed to create output directory","errorType":"exception","errorClass":"JUnitException","httpStatus":null,"severity":"error","filePath":"junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java","lineNumber":197,"sourceCode":"\t\t\t() -> \"name must not contain path separators: \" + name);\n\t\ttry {\n\t\t\taction.accept(path);\n\t\t}\n\t\tcatch (Throwable t) {\n\t\t\tUnrecoverableExceptions.rethrowIfUnrecoverable(t);\n\t\t\tthrow new JUnitException(\"Failed to publish path\", t);\n\t\t}\n\t\tPreconditions.condition(Files.exists(path), () -> \"Published path must exist: \" + path);\n\t\tFileEntry fileEntry = fileEntryCreator.apply(path);\n\t\tthis.engineExecutionListener.fileEntryPublished(this.testDescriptor, fileEntry);\n\t}\n\n\tprivate Path createOutputDirectory() {\n\t\ttry {\n\t\t\treturn configuration.getOutputDirectoryCreator().createOutputDirectory(this.testDescriptor);\n\t\t}\n\t\tcatch (IOException e) {\n\t\t\tthrow new JUnitException(\"Failed to create output directory\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic Optional<ExtensionContext> getParent() {\n\t\treturn Optional.ofNullable(this.parent);\n\t}\n\n\t@Override\n\tpublic ExtensionContext getRoot() {\n\t\tif (this.parent != null) {\n\t\t\treturn this.parent.getRoot();\n\t\t}\n\t\treturn this;\n\t}\n\n\tprotected T getTestDescriptor() {\n\t\treturn this.testDescriptor;","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/junit-team/junit5/blob/956246301e03d757539f7b76dd5a91f298637563/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java#L179-L215","documentation":"Thrown by AbstractExtensionContext.createOutputDirectory() when the JupiterConfiguration's OutputDirectoryCreator.createOutputDirectory(testDescriptor) raises an IOException. The output directory is the parent location into which publishFile/publishDirectory resolve file names, so its creation is a precondition for any file-publishing API.","triggerScenarios":"Calling ExtensionContext.publishFile(...) or publishDirectory(...) when the configured OutputDirectoryCreator cannot create the directory — e.g. the derived path is rooted at a read-only location, the parent does not exist and cannot be created, or a security manager denies access.","commonSituations":"A custom OutputDirectoryCreator registered via LauncherDiscoveryRequestBuilder that computes a path from the test descriptor pointing into a non-writable area; running tests as a user without write permission to the configured base; container/CI environments with a read-only workspace; a creator that relies on a system property (junit.platform.output.*) that was not set, defaulting to an invalid root.","solutions":["Check the cause IOException for the exact path and OS error (permission denied, no such file, read-only file system).","Ensure the base output directory configured for the launcher is writable by the test JVM user.","If using a custom OutputDirectoryCreator, make it create missing parent directories (Files.createDirectories) and fall back to a sane default.","Set/verify the relevant configuration parameter that determines the output location before launching the test plan."],"exampleFix":"// before — creator returns a path under a read-only root\nLauncherDiscoveryRequestBuilder.request()\n    .configurationParameter(\"junit.jupiter.output.directory\", \"/opt/read-only/reports\")\n    .build();\n// after\nLauncherDiscoveryRequestBuilder.request()\n    .configurationParameter(\"junit.jupiter.output.directory\", System.getProperty(\"java.io.tmpdir\") + \"/junit-reports\")\n    .build();","handlingStrategy":"validation","validationCode":"// Validate the output directory creator base before launch\nPath base = Paths.get(System.getProperty(\"junit.jupiter.output.dir\", \"build/junit-output\"));\ntry { Files.createDirectories(base); } catch (IOException e) { throw new IllegalStateException(e); }\nif (!Files.isWritable(base)) throw new IllegalStateException(\"Not writable: \" + base);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set junit.jupiter.output.directory to a writable, pre-created path.","If supplying a custom OutputDirectoryCreator, ensure it calls Files.createDirectories on the parent.","Run the test JVM as a user with write permission to the output root."],"tags":["junit-jupiter","extension","io","configuration","publishing"],"analyzedSha":"956246301e03d757539f7b76dd5a91f298637563","analyzedAt":"2026-08-04T19:25:17.049Z","schemaVersion":2}