junit-team/junit5 · error · JUnitException
Failed to publish path
Error message
Failed to publish path
What it means
Thrown by AbstractExtensionContext.publishFileEntry() when the ThrowingConsumer<Path> action passed to ExtensionContext.publishFile() or publishDirectory() throws while writing to the resolved path. The engine catches the Throwable, rethrows unrecoverable exceptions, and wraps the rest in a JUnitException so the failure is attributable to the file-publishing step rather than the user's arbitrary exception type.
Source
Thrown at junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java:185
};
publishFileEntry(name, enhancedAction, path -> {
Preconditions.condition(Files.isDirectory(path), () -> "Published path must be a directory: " + path);
return FileEntry.from(path, null);
});
}
private void publishFileEntry(String name, ThrowingConsumer<Path> action,
Function<Path, FileEntry> fileEntryCreator) {
Path dir = createOutputDirectory();
Path path = dir.resolve(name);
Preconditions.condition(path.getParent() != null && path.getParent().equals(dir),
() -> "name must not contain path separators: " + name);
try {
action.accept(path);
}
catch (Throwable t) {
UnrecoverableExceptions.rethrowIfUnrecoverable(t);
throw new JUnitException("Failed to publish path", t);
}
Preconditions.condition(Files.exists(path), () -> "Published path must exist: " + path);
FileEntry fileEntry = fileEntryCreator.apply(path);
this.engineExecutionListener.fileEntryPublished(this.testDescriptor, fileEntry);
}
private Path createOutputDirectory() {
try {
return configuration.getOutputDirectoryCreator().createOutputDirectory(this.testDescriptor);
}
catch (IOException e) {
throw new JUnitException("Failed to create output directory", e);
}
}
@Override
public Optional<ExtensionContext> getParent() {
return Optional.ofNullable(this.parent);View on GitHub (pinned to 956246301e)
Solutions
- Inspect the cause (getCause()) of the JUnitException — it is the original throwable from your action and pinpoints the failing I/O or logic step.
- Ensure your publishFile/publishDirectory action performs all writes to the supplied Path and closes all streams in a try-with-resources before returning.
- Verify the output directory is writable and has free space; the path is created by the configured OutputDirectoryCreator.
- Catch expected business exceptions inside your action and either recover or rethrow as a meaningful message, since the engine will wrap anything thrown.
Example fix
// before
context.publishFile("report.html", MediaType.TEXT_HTML, path -> {
Files.writeString(path, buildHtml()); // buildHtml() may throw -> wrapped as 'Failed to publish path'
});
// after
context.publishFile("report.html", MediaType.TEXT_HTML, path -> {
String html;
try { html = buildHtml(); }
catch (Exception e) { throw new IOException("Failed to build report HTML", e); }
Files.writeString(path, html);
}); Defensive patterns
Strategy: try-catch
Validate before calling
// Validate writability before calling publishFile
Path outDir = Paths.get(System.getProperty("junit.jupiter.output.dir", "build/reports"));
if (!Files.isWritable(outDir)) {
throw new IllegalStateException("Output dir not writable: " + outDir);
} Try / catch
try {
context.publishFile("report.html", MediaType.TEXT_HTML, this::writeReport);
} catch (JUnitException e) {
Throwable cause = e.getCause();
log.error("publishFile failed: {}", cause.getMessage());
// fall back to in-test reporting or rethrow
} Prevention
- Make publishFile actions self-contained: open and close all streams inside the lambda.
- Pre-check that the configured output directory is writable.
- Throw IOException with a clear message from the action so the wrapped cause is actionable.
When it happens
Trigger: Calling ExtensionContext.publishFile(name, mediaType, action) or publishDirectory(name, action) where the action lambda throws an IOException, RuntimeException, or Error while writing to the supplied Path. Also fires if the action runs but a later Files.exists check inside the action's own writes fails due to the action rethrowing.
Common situations: Extensions that publish reports/screenshots/artifacts via publishFile and write to a path on a full or read-only disk, an action that opens a stream and forgets to handle a broken pipe, or an action whose content-generation logic throws (e.g. serialization failure). Also when the configured output directory is on a network mount that drops mid-write.
Related errors
- Failed to create output directory
- Failed to create default temp directory
- Failed to copy files to the output directory
- The following TestInstanceFactory extensions were registered
- TestInstanceFactory [%s] failed to instantiate test class [%
AI-assisted analysis of junit-team/junit5@956246301e (2026-08-04).
Data as JSON: /data/errors/abe6e1a3211ec843.json.
Report an issue: GitHub.