junit-team/junit5 · error · UncheckedIOException
Failed to start process
Error message
Failed to start process
What it means
Thrown as an UncheckedIOException by GitInfoCollector.ProcessExecutor.startProcess() when ProcessBuilder.start() fails to spawn the git child process. Note: startProcess is called OUTSIDE exec()'s try block, so this exception propagates even during the initial 'git --version' availability probe — it is not swallowed by exec()'s 'catch (IOException ignore)'. It ultimately surfaces wrapped inside error 145 ('Failed to initialize XML events writer'). GitInfoCollector is a package-private interface invoked only when junit.platform.reporting.open.xml.git.enabled is true.
Solutions
- Disable git metadata collection: -Djunit.platform.reporting.open.xml.git.enabled=false (the default).
- Install git in the CI/container image and ensure it is on the PATH of the JVM process.
- Raise process/file-descriptor limits (ulimit -u, ulimit -n) on the build agent.
- Confirm the listener's working directory still exists at testPlanExecutionStarted time.
Example fix
// before -Djunit.platform.reporting.open.xml.git.enabled=true // after -Djunit.platform.reporting.open.xml.git.enabled=false
Defensive patterns
Strategy: fallback
Validate before calling
// Only enable git collection if git is actually runnable on this host.
boolean gitEnabled = Boolean.getBoolean(
"junit.platform.reporting.open.xml.git.enabled");
if (gitEnabled) {
try {
Process p = new ProcessBuilder("git", "--version").start();
boolean ok = p.waitFor(5, TimeUnit.SECONDS) && p.exitValue() == 0;
p.destroyForcibly();
if (!ok) {
System.clearProperty("junit.platform.reporting.open.xml.git.enabled");
}
} catch (IOException | InterruptedException e) {
System.clearProperty("junit.platform.reporting.open.xml.git.enabled");
}
} Try / catch
// Users do not call GitInfoCollector directly (package-private). It surfaces wrapped
// as JUnitException("Failed to initialize XML events writer"). Catch at the launcher level:
try {
launcher.execute(request);
} catch (JUnitException e) {
Throwable c = e.getCause();
if (c instanceof UncheckedIOException uio
&& uio.getMessage().equals("Failed to start process")) {
// Git unavailable in this environment; disable and retry, or report and skip.
}
} Prevention
- Default junit.platform.reporting.open.xml.git.enabled to false in minimal containers.
- Install git in CI images and verify 'git --version' runs as the build user before enabling.
- Raise ulimit -u / ulimit -n on busy build agents to avoid fork failures.
- Confirm the listener's working directory exists at testPlanExecutionStarted time.
When it happens
Trigger: Enabling junit.platform.reporting.open.xml.git.enabled=true on a machine where the git binary is not installed or not on the PATH; the OS denying fork()/exec() due to pid or file-descriptor limits (cgroup-constrained containers); workingDir.toFile() returning null because the configured working dir is not a directory; the git binary disappearing between the version probe and a later command.
Common situations: Minimal Docker/Alpine CI images that omit git; distroless JVM images; sandboxes (sshd chroot, macOS sandbox) that block process spawning; ulimit -u/-n hit on a busy build agent; the working directory was deleted between the listener constructor (Path.of('.').toAbsolutePath()) and git collection.
Related errors
- Failed to create output dir
- Failed to close XML events file
- Failed to connect to socket on port
- Failed to create output directory
- Failed to create output file
AI-assisted analysis of junit-team/junit5@f070c699a0 (2026-08-11).
Data as JSON: /api/errors/49342fa6b269c3d5.
Report an issue: GitHub.
Appendix: source
Thrown at junit-platform-reporting/src/main/java/org/junit/platform/reporting/open/xml/GitInfoCollector.java:171
catch (IOException ignore) {
return Optional.empty();
}
finally {
process.destroyForcibly();
}
}
private static BufferedReader newBufferedReader(InputStream stream) {
return new BufferedReader(new InputStreamReader(stream, Charset.defaultCharset()));
}
private Process startProcess(String[] command) {
Process process;
try {
process = new ProcessBuilder().directory(workingDir.toFile()).command(command).start();
}
catch (IOException e) {
throw new UncheckedIOException("Failed to start process", e);
}
return process;
}
private static void readAllChars(Reader reader, BiConsumer<char[], Integer> consumer) throws IOException {
char[] buffer = new char[1024];
int numChars;
while ((numChars = reader.read(buffer)) != -1) {
consumer.accept(buffer, numChars);
}
}
private static String trimAtEnd(StringBuilder value) {
int endIndex = value.length();
for (int i = value.length() - 1; i >= 0; i--) {
if (Character.isWhitespace(value.charAt(i))) {
endIndex--;
break;View on GitHub (pinned to f070c699a0)