GoogleContainerTools/jib · error · CacheCorruptedException

No or multiple layer files found for layer hash <layerDigest

Error message

No or multiple layer files found for layer hash <layerDigest> in directory: <layerDirectory>

What it means

Cached layers are stored one compressed layer file per digest directory. retrieve(layerDigest) lists the layer directory and requires exactly one layer file; zero files (missing layer) or more than one (duplicate) means the cache is inconsistent, and CacheCorruptedException is thrown naming the digest and directory.

Source

Thrown at jib-core/src/main/java/com/google/cloud/tools/jib/cache/CacheStorageReader.java:160

   * Retrieves the {@link CachedLayer} for the layer with digest {@code layerDigest}.
   *
   * @param layerDigest the layer digest
   * @return the {@link CachedLayer} referenced by the layer digest, if found
   * @throws CacheCorruptedException if the cache was found to be corrupted
   * @throws IOException if an I/O exception occurs
   */
  Optional<CachedLayer> retrieve(DescriptorDigest layerDigest)
      throws IOException, CacheCorruptedException {
    Path layerDirectory = cacheStorageFiles.getLayerDirectory(layerDigest);
    if (!Files.exists(layerDirectory)) {
      return Optional.empty();
    }

    try (Stream<Path> files = Files.list(layerDirectory)) {
      List<Path> layerFiles =
          files.filter(CacheStorageFiles::isLayerFile).collect(Collectors.toList());
      if (layerFiles.size() != 1) {
        throw new CacheCorruptedException(
            cacheStorageFiles.getCacheDirectory(),
            "No or multiple layer files found for layer hash "
                + layerDigest.getHash()
                + " in directory: "
                + layerDirectory);
      }

      Path layerFile = layerFiles.get(0);
      return Optional.of(
          CachedLayer.builder()
              .setLayerDigest(layerDigest)
              .setLayerSize(Files.size(layerFile))
              .setLayerBlob(Blobs.from(layerFile))
              .setLayerDiffId(cacheStorageFiles.getDigestFromFilename(layerFile))
              .build());
    }
  }

View on GitHub (pinned to fb949e2676)

Solutions

  1. Delete the affected layer directory (or the whole cache) so the layer is re-fetched
  2. Disable concurrent Jib builds sharing one cache directory, or give each a separate cache
  3. Exclude the cache directory from antivirus scanning and cleanup jobs
  4. Re-run the build after clearing ~/.cache/google-cloud-tools-java/jib

Example fix

// before: build fails on layer sha256:abc...
// after: remove just that layer
rm -rf ~/.cache/google-cloud-tools-java/jib/layers/sha256:abc...
Defensive patterns

Strategy: try-catch

Validate before calling

long n = Files.list(layerDir).filter(Files::isRegularFile).count();
if (n != 1) deleteRecursively(layerDir);

Try / catch

try {
  build();
} catch (CacheCorruptedException e) {
  String dir = extractLayerDir(e.getMessage());
  if (dir != null) deleteRecursively(Path.of(dir)); else wipeCache();
  build();
}

Prevention

When it happens

Trigger: CacheStorageReader.retrieve() is called (during layer push/pull flows) and Files.list(layerDirectory) filtered by CacheStorageFiles::isLayerFile yields a count other than 1.

Common situations: Antivirus or cleanup tools deleting cache files, two Jib processes writing the same layer concurrently, partial download interrupted leaving zero/extra files, manually copying files into the cache.

Related errors


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