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
- Delete the affected layer directory (or the whole cache) so the layer is re-fetched
- Disable concurrent Jib builds sharing one cache directory, or give each a separate cache
- Exclude the cache directory from antivirus scanning and cleanup jobs
- 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
- Serialize builds sharing a cache or use per-build caches
- Add cache dir to AV exclusions
- Never manually edit the layers directory
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
- Unable to create cache directory for project path: ${path} -
- CacheDirectoryCreationException wrapping IOException from ca
- Layer file did not include valid hash: <layerFile>
- Manifest cache empty
- Manifest(s) missing
AI-assisted analysis of GoogleContainerTools/jib@fb949e2676 (2026-09-06).
Data as JSON: /api/errors/11ce41bfb5825db2.
Report an issue: GitHub.