bazelbuild/bazel · error · RuntimeException

Could not write exit file at ${file}

Error message

Could not write exit file at ${file}

What it means

Thrown by JUnit4Runner.exitFileActive when the runner cannot truncate the file named by the TEST_PREMATURE_EXIT_FILE environment variable. Bazel's test harness sets this variable and expects the runner to empty the file at startup as a liveness signal; an IOException while opening or writing it is wrapped in a RuntimeException and aborts the run before any test executes.

Source

Thrown at src/java_tools/junitrunner/java/com/google/testing/junit/runner/junit4/JUnit4Runner.java:127

      Runtime.getRuntime().removeShutdownHook(shutdownHook);
    }
  }

  // Support for "premature exit files": Tests may write this to communicate
  // to the runner in case of premature exit.
  private static File getExitFile() {
    String exitFile = System.getenv("TEST_PREMATURE_EXIT_FILE");
    return exitFile == null ? null : new File(exitFile);
  }

  private static void exitFileActive(@Nullable File file) {
    if (file != null) {
      try (FileOutputStream outputStream = new FileOutputStream(file, false)) {
        // Overwrite file content.
        outputStream.write(new byte[0]);
        outputStream.close();
      } catch (IOException e) {
        throw new RuntimeException("Could not write exit file at " + file, e);
      }
    }
  }

  private void exitFileInactive(@Nullable File file) {
    if (file != null) {
      try {
        file.delete();
      } catch (Throwable t) {
        // Just print the stack trace, to avoid masking a real test failure.
        t.printStackTrace(testRunnerOut);
      }
    }
  }

  // VisibleForTesting
  TestSuiteModel getModel() {
    return modelSupplier.get();

View on GitHub (pinned to e6e199d060)

Solutions

  1. If running the runner by hand, unset TEST_PREMATURE_EXIT_FILE (the code tolerates a null file).
  2. Otherwise make the parent directory of the path exist and be writable by the test process (mkdir -p, chmod, correct volume mounts).
  3. Free disk space / fix filesystem permissions on the sandbox tree and re-run bazel test.
  4. When wrapping the runner, catch and report the IOException with the file path before it masks the real test result.

Example fix

# before
TEST_PREMATURE_EXIT_FILE=/nonexistent/dir/exit_file java ... JUnit4Runner ...
# after (manual run)
unset TEST_PREMATURE_EXIT_FILE
java ... JUnit4Runner ...
Defensive patterns

Strategy: validation

Validate before calling

// before running the runner in-process
String exitFile = System.getenv("TEST_PREMATURE_EXIT_FILE");
if (exitFile != null) {
  File f = new File(exitFile);
  File dir = f.getParentFile();
  if (dir != null && !(dir.isDirectory() && dir.canWrite())) {
    throw new IllegalStateException("TEST_PREMATURE_EXIT_FILE dir not writable: " + dir);
  }
}

Prevention

When it happens

Trigger: TEST_PREMATURE_EXIT_FILE points into a directory that does not exist, is read-only, or is not writable by the test user; the path is on a full disk or a filesystem that rejects the open (e.g. path names a directory).

Common situations: Running the JUnit4Runner manually with copied harness environment variables after the Bazel sandbox was cleaned up; docker containers where /tmp is mounted read-only; disk-full CI agents; SELinux denying writes to the sandbox path.

Related errors


AI-assisted analysis of bazelbuild/bazel@e6e199d060 (2026-08-14). Data as JSON: /api/errors/3c563e48f4053a2d. Report an issue: GitHub.