GoogleContainerTools/jib · error · CacheCorruptedException
Schema 1 manifests corrupted
Error message
Schema 1 manifests corrupted
What it means
For schema 1 (Docker v2.1) cached manifests, verifyImageMetadata requires that no manifest list was stored and that no config blobs are present, since schema 1 manifests embed their config differently. If either is present, the cached schema-1 metadata is inconsistent and CacheCorruptedException('Schema 1 manifests corrupted') is thrown.
Source
Thrown at jib-core/src/main/java/com/google/cloud/tools/jib/cache/CacheStorageReader.java:62
@VisibleForTesting
static void verifyImageMetadata(ImageMetadataTemplate metadata, Path metadataCacheDirectory)
throws CacheCorruptedException {
List<ManifestAndConfigTemplate> manifestsAndConfigs = metadata.getManifestsAndConfigs();
if (manifestsAndConfigs.isEmpty()) {
throw new CacheCorruptedException(metadataCacheDirectory, "Manifest cache empty");
}
if (manifestsAndConfigs.stream().anyMatch(entry -> entry.getManifest() == null)) {
throw new CacheCorruptedException(metadataCacheDirectory, "Manifest(s) missing");
}
if (metadata.getManifestList() == null && manifestsAndConfigs.size() != 1) {
throw new CacheCorruptedException(metadataCacheDirectory, "Manifest list missing");
}
ManifestTemplate firstManifest = manifestsAndConfigs.get(0).getManifest();
if (firstManifest instanceof V21ManifestTemplate) {
if (metadata.getManifestList() != null
|| manifestsAndConfigs.stream().anyMatch(entry -> entry.getConfig() != null)) {
throw new CacheCorruptedException(metadataCacheDirectory, "Schema 1 manifests corrupted");
}
} else if (firstManifest instanceof BuildableManifestTemplate) {
if (manifestsAndConfigs.stream().anyMatch(entry -> entry.getConfig() == null)) {
throw new CacheCorruptedException(metadataCacheDirectory, "Schema 2 manifests corrupted");
}
if (metadata.getManifestList() != null
&& manifestsAndConfigs.stream().anyMatch(entry -> entry.getManifestDigest() == null)) {
throw new CacheCorruptedException(metadataCacheDirectory, "Schema 2 manifests corrupted");
}
} else {
throw new CacheCorruptedException(
metadataCacheDirectory, "Unknown manifest type: " + firstManifest);
}
}
private final CacheStorageFiles cacheStorageFiles;
CacheStorageReader(CacheStorageFiles cacheStorageFiles) {View on GitHub (pinned to fb949e2676)
Solutions
- Clear the Jib cache directory and rebuild online so a single consistent metadata set is written
- Prefer a base image served as schema 2/OCI (most modern registries); legacy schema 1 is deprecated by registries
- Ensure only one build process uses the cache directory at a time (or use separate cache dirs per build)
- Upgrade Jib to a current version, which handles registry manifest schema negotiation consistently
Example fix
// before from openjdk:8 // very old tag, schema 1 registry response, stale cache // after rm -rf ~/.cache/google-cloud-tools-jib <from><image>eclipse-temurin:17-jre</image></from> // schema 2/OCI base image
Defensive patterns
Strategy: fallback
Validate before calling
crane manifest $BASE_IMAGE | jq -e '.schemaVersion == 2'
Prevention
- Use schema 2/OCI base images
When it happens
Trigger: retrieveMetadata finds firstManifest instanceof V21ManifestTemplate while getManifestList() != null or any entry has getConfig() != null — schema-1 entries mixed with schema-2-style metadata in the cache.
Common situations: Base image registry serves schema 1 for very old images (e.g. legacy Docker Hub images) and the cache got mixed writes; cache written by an older Jib version then read by a newer one; concurrent builds writing different manifest schemas to the same cache.
Related errors
- Manifest(s) missing
- Layer file did not include valid hash: <layerFile>
- Manifest cache empty
- Manifest list missing
- Dependency required by the JAR (as specified in `Class-Path`
AI-assisted analysis of GoogleContainerTools/jib@fb949e2676 (2026-09-06).
Data as JSON: /api/errors/b52ec42fcfad7b8d.
Report an issue: GitHub.