GoogleContainerTools/jib · error · LayerCountMismatchException

Invalid base image format: manifest contains <n> layers, but

Error message

Invalid base image format: manifest contains <n> layers, but container configuration contains <n> layers

What it means

When loading a base image from a Docker tar archive (cacheDockerImageTar), Jib cross-checks the number of layer files listed in the tar's manifest with the layer count in the container configuration JSON. A mismatch means the tar is malformed or inconsistent, so LayerCountMismatchException is thrown with both counts. This guards against producing a broken image built on inconsistent metadata.

Source

Thrown at jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/LocalBaseImageSteps.java:237

      try (InputStream manifestStream =
          Files.newInputStream(destination.resolve("manifest.json"))) {
        loadManifest =
            JsonMapper.builder()
                .configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true)
                .build()
                .readValue(manifestStream, DockerManifestEntryTemplate[].class)[0];
      }

      Path configPath = destination.resolve(loadManifest.getConfig());
      ContainerConfigurationTemplate configurationTemplate =
          JsonTemplateMapper.readJsonFromFile(configPath, ContainerConfigurationTemplate.class);
      // Don't compute the digest of the loaded Java JSON instance.
      BlobDescriptor originalConfigDescriptor =
          Blobs.from(configPath).writeTo(ByteStreams.nullOutputStream());

      List<String> layerFiles = loadManifest.getLayerFiles();
      if (configurationTemplate.getLayerCount() != layerFiles.size()) {
        throw new LayerCountMismatchException(
            "Invalid base image format: manifest contains "
                + layerFiles.size()
                + " layers, but container configuration contains "
                + configurationTemplate.getLayerCount()
                + " layers");
      }
      buildContext
          .getBaseImageLayersCache()
          .writeLocalConfig(originalConfigDescriptor.getDigest(), configurationTemplate);

      // Check the first layer to see if the layers are compressed already. 'docker save' output
      // is uncompressed, but a jib-built tar has compressed layers.
      boolean layersAreCompressed =
          !layerFiles.isEmpty() && isGzipped(destination.resolve(layerFiles.get(0)));

      // Process layer blobs
      try (ProgressEventDispatcher progressEventDispatcher =
          progressEventDispatcherFactory.create(

View on GitHub (pinned to fb949e2676)

Solutions

  1. Regenerate the tarball: `docker save <image> -o base.tar` from an intact Docker daemon and retry.
  2. Verify the tar integrity: manifest.json layer count vs config JSON diff_ids; restore missing layer files.
  3. Use a registry base image reference (e.g. eclipse-temurin:17) instead of a local tar to bypass tar loading.
  4. Re-pull the base image (`docker pull`) to replace a corrupt local image, then re-save.
  5. If using a third-party tool to build tars, fix or upgrade that tool to emit matching manifest/config.

Example fix

// before
jib.image = "docker://custom-base.tar" // tar with mismatched layers
// after
// regenerate cleanly
docker pull eclipse-temurin:17
docker save eclipse-temurin:17 -o base.tar
jib.image = "docker://base.tar"
Defensive patterns

Strategy: validation

Validate before calling

// Inspect tar before handing to jib
int manifestLayers = readManifestLayerCount(baseTar); // from manifest.json
int configLayers = readConfigDiffIdCount(baseTar);    // from config JSON rootfs.diff_ids
if (manifestLayers != configLayers) throw new IllegalArgumentException("corrupt base tar");

Type guard

null

Try / catch

try { /* jib build from docker tar */ } catch (LayerCountMismatchException e) { /* regenerate tarball with docker save */ }

Prevention

When it happens

Trigger: Running `jib build --image=...` with a base image passed via `docker:` tarball (or fromDaemon) whose manifest.json lists a different number of layers than the config JSON's rootfs diff_ids - e.g. manually edited tars, tars produced by non-Docker tools, or partially extracted tars.

Common situations: Building from a `docker save` output that was modified or truncated; third-party image tarball generators producing inconsistent manifests; copying/tarring images incorrectly (missing layer files); older OCI/Docker format variants.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


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