{"record":{"id":"abe6e1a3211ec843","repo":"junit-team/junit5","slug":"failed-to-publish-path","errorCode":null,"errorMessage":"Failed to publish path","messagePattern":"Failed to publish path","errorType":"exception","errorClass":"JUnitException","httpStatus":null,"severity":"error","filePath":"junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java","lineNumber":185,"sourceCode":"\t\t};\n\t\tpublishFileEntry(name, enhancedAction, path -> {\n\t\t\tPreconditions.condition(Files.isDirectory(path), () -> \"Published path must be a directory: \" + path);\n\t\t\treturn FileEntry.from(path, null);\n\t\t});\n\t}\n\n\tprivate void publishFileEntry(String name, ThrowingConsumer<Path> action,\n\t\t\tFunction<Path, FileEntry> fileEntryCreator) {\n\t\tPath dir = createOutputDirectory();\n\t\tPath path = dir.resolve(name);\n\t\tPreconditions.condition(path.getParent() != null && path.getParent().equals(dir),\n\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);","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/junit-team/junit5/blob/f070c699a08b5d8393df9afd147af5c5e90bb21b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java#L167-L203","documentation":"Thrown by AbstractExtensionContext.publishFileEntry when the ThrowingConsumer<Path> action that writes a published file entry (e.g. a @Write wrapper or ExtensionContext.publishFile call) raises any Throwable. The action is invoked against a path resolved inside the per-test output directory; any failure (disk full, permission denied, IO error) is wrapped into a JUnitException with the cause attached rather than being swallowed.","triggerScenarios":"Calling ExtensionContext.publishFile(String, ThrowingConsumer) or publishFileAsHex where the consumer lambda throws an IOException, RuntimeException, or other error while writing to the resolved Path. The throw site is action.accept(path) inside publishFileEntry.","commonSituations":"Test directory not writable (CI sandbox / read-only mount), out of disk space, a nested path separator slipped past the precondition (very rare), or a custom extension that overrides publishing and writes more bytes than the filesystem accepts.","solutions":["Check the attached cause (getCause()) for the real IOException and address that: free disk space, fix permissions on the output directory, or remove the read-only mount.","Verify the output directory creator returns a writable location via the junit.platform.output.dir configuration or JupiterConfiguration outputDirectoryCreator.","Ensure the published file name passed to publishFile does not itself trigger an IOException in your writer lambda (e.g. close streams before returning)."],"exampleFix":"// before\ncontext.publishFile(\"report.txt\", path -> {\n    Files.writeString(path, payload); // throws if disk full / read-only\n});\n// after - ensure target dir is writable before publishing\nPath outDir = context.getConfigurationDirectory();\nif (!Files.isWritable(outDir)) throw new IllegalStateException(\"output dir not writable: \" + outDir);\ncontext.publishFile(\"report.txt\", path -> Files.writeString(path, payload));","handlingStrategy":"try-catch","validationCode":"Path outDir = context.getConfigurationDirectory(); // or however you obtain it\nif (outDir == null || !Files.isWritable(outDir)) {\n    throw new IllegalStateException(\"Output dir not writable: \" + outDir);\n}\ncontext.publishFile(\"report.txt\", path -> Files.writeString(path, payload));","typeGuard":null,"tryCatchPattern":"try {\n    context.publishFile(\"report.txt\", path -> Files.writeString(path, payload));\n} catch (JUnitException e) {\n    Throwable cause = e.getCause();\n    log.error(\"publish failed due to: {}\", cause == null ? e : cause);\n    throw e;\n}","preventionTips":["Verify the configured output directory is writable before publishing.","Catch JUnitException only at the test orchestration layer and inspect getCause() for the real IOException.","Keep publish lambdas small so the failure is attributable to a single IO operation."],"tags":["io","publish-file","extension-context","filesystem"],"backgroundTag":null,"analyzedSha":"f070c699a08b5d8393df9afd147af5c5e90bb21b","analyzedAt":"2026-08-11T20:31:00.530Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}