jdx/mise · error

{image_dir.display}: expected exactly one manifest in index.

Error message

{image_dir.display}: expected exactly one manifest in index.json

What it means

When loading an OCI image layout into docker, load_into_docker reads index.json and expects exactly one manifest entry. This error is thrown when the OCI image index contains zero or multiple manifests, since the loader cannot decide which manifest to load and does not implement multi-manifest (multi-arch/attestation) selection.

Source

Thrown at src/oci/docker_archive.rs:46

    #[serde(rename = "Config")]
    config: String,
    #[serde(rename = "RepoTags")]
    repo_tags: Vec<String>,
    #[serde(rename = "Layers")]
    layers: Vec<String>,
}

/// Stream the OCI layout at `image_dir` into `docker load`, tagging the
/// loaded image as `tag`.
pub(crate) fn load_into_docker(image_dir: &Path, tag: &str) -> Result<()> {
    let layout = ImageLayout {
        root: image_dir.to_path_buf(),
    };
    let index_bytes = crate::file::read(image_dir.join("index.json"))?;
    let index: ImageIndex = serde_json::from_slice(&index_bytes).wrap_err("parsing index.json")?;
    let manifest_desc = match index.manifests.as_slice() {
        [one] => one,
        _ => bail!(
            "{}: expected exactly one manifest in index.json",
            image_dir.display()
        ),
    };
    let manifest_bytes = layout.read_blob(&manifest_desc.digest)?;
    let manifest: ImageManifest =
        serde_json::from_slice(&manifest_bytes).wrap_err("parsing image manifest blob")?;
    let config_bytes = layout.read_blob(&manifest.config.digest)?;

    // Validate every layer digest before it's used as a path component in
    // `write_docker_archive` (which reads via `blob_path`, bypassing the
    // check `read_blob` performs) — a crafted `--image-dir` layout could
    // otherwise escape the blobs directory with `sha256:../…`.
    for layer in &manifest.layers {
        crate::oci::layout::validate_sha256_digest(&layer.digest)?;
    }

    let mut command = Command::new("docker");

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Rebuild/export the image for a single platform (e.g. `docker buildx build --platform linux/amd64` with `--provenance=false --sbom=false`) so index.json has exactly one manifest.
  2. Inspect index.json in image_dir and remove extra manifest descriptors, keeping only the one for your platform.
  3. Regenerate the OCI layout with the same mise tool that produced it originally rather than hand-modifying index.json.

Example fix

// before (index.json with 2 manifests from buildx attestation)
// docker buildx build --platform linux/amd64,linux/arm64 -o type=oci,dest=img.tar
// after
docker buildx build --platform linux/amd64 --provenance=false --sbom=false -o type=oci,dest=img.tar
Defensive patterns

Strategy: validation

Validate before calling

const index = JSON.parse(fs.readFileSync(path.join(imageDir, "index.json")));
if (index.manifests.length !== 1) {
  throw new Error(`need exactly 1 manifest, found ${index.manifests.length}; rebuild single-platform`);
}

Try / catch

match load_into_docker(&image_dir) {
    Err(e) if e.to_string().contains("expected exactly one manifest") => {
        eprintln!("rebuild single-platform (no attestation manifests) and retry");
    }
    r => r,
}

Prevention

When it happens

Trigger: Pointing load_into_docker (via `mise oci load` or similar) at an image directory whose index.json has 0 or >=2 entries in the `manifests` array — e.g. a multi-arch index produced by buildx, or a truncated/incorrectly generated layout.

Common situations: Building with docker buildx producing a manifest list instead of a single-platform image; hand-editing or regenerating index.json and leaving stale manifest descriptors; concatenating or exporting images with attestation manifests.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/3d9f71252b72b8c6. Report an issue: GitHub.