GoogleContainerTools/jib · error · IllegalStateException

Cannot enable reproducible timestamps. They can only be enab

Error message

Cannot enable reproducible timestamps. They can only be enabled when the target root doesn't exist or is an empty directory

What it means

TarExtractor.extract throws IllegalStateException when reproducible timestamps are requested but the destination directory already exists and is non-empty. Reproducible extraction requires writing into a fresh location so entry order/timestamps are deterministic; Jib fails fast rather than mixing old and new content.

Source

Thrown at jib-core/src/main/java/com/google/cloud/tools/jib/tar/TarExtractor.java:67

    extract(source, destination, false);
  }

  /**
   * Extracts a tarball to the specified destination.
   *
   * @param source the tarball to extract
   * @param destination the output directory
   * @param enableReproducibleTimestamps whether or not reproducible timestamps should be used
   * @throws IOException if extraction fails
   * @throws IllegalStateException when reproducible timestamps are enabled but the target root used
   *     for extracting the tar contents is not empty
   */
  public static void extract(Path source, Path destination, boolean enableReproducibleTimestamps)
      throws IOException {
    if (enableReproducibleTimestamps
        && Files.isDirectory(destination)
        && destination.toFile().list().length != 0) {
      throw new IllegalStateException(
          "Cannot enable reproducible timestamps. They can only be enabled when the target root doesn't exist or is an empty directory");
    }
    String canonicalDestination = destination.toFile().getCanonicalPath();
    List<TarArchiveEntry> entries = new ArrayList<>();
    try (InputStream in = new BufferedInputStream(Files.newInputStream(source));
        TarArchiveInputStream tarArchiveInputStream = new TarArchiveInputStream(in)) {
      for (TarArchiveEntry entry = tarArchiveInputStream.getNextEntry();
          entry != null;
          entry = tarArchiveInputStream.getNextEntry()) {
        entries.add(entry);
        Path entryPath = destination.resolve(entry.getName());

        String canonicalTarget = entryPath.toFile().getCanonicalPath();
        if (!canonicalTarget.startsWith(canonicalDestination + File.separator)) {
          String offender = entry.getName() + " from " + source;
          throw new IOException("Blocked unzipping files outside destination: " + offender);
        }
        if (entry.isDirectory()) {

View on GitHub (pinned to fb949e2676)

Solutions

  1. Delete or empty the destination directory before calling extract with enableReproducibleTimestamps=true.
  2. Pass enableReproducibleTimestamps=false if merging into an existing directory is intentional.
  3. Extract to a fresh temporary directory each run.
  4. Add cleanup to your build script (e.g. gradle clean or rm -rf dest).

Example fix

// before
TarExtractor.extract(tarPath, dest, true);
// after
Files.walkFileTree(dest, deleteVisitor); // or FileUtils.deleteDirectory(dest)
TarExtractor.extract(tarPath, dest, true);
Defensive patterns

Strategy: validation

Validate before calling

// Ensure destination is fresh before reproducible extraction
if (java.nio.file.Files.isDirectory(dest)
    && java.util.Objects.requireNonNull(dest.toFile().list()).length > 0) {
  throw new IllegalArgumentException("Destination must be empty: " + dest);
}

Try / catch

try { TarExtractor.extract(src, dest, true); } catch (IllegalStateException e) { org.apache.commons.io.FileUtils.deleteDirectory(dest.toFile()); TarExtractor.extract(src, dest, true); }

Prevention

When it happens

Trigger: Calling TarExtractor.extract(source, destination, true) where destination is an existing directory containing files; re-running extraction into the same folder with enableReproducibleTimestamps=true.

Common situations: Re-running a build/extraction script without cleaning the target dir; extracting layers into a cached workspace that already has prior contents.

Related errors


AI-assisted analysis of GoogleContainerTools/jib@fb949e2676 (2026-09-06). Data as JSON: /api/errors/adeeb022f27f61e5. Report an issue: GitHub.