{"record":{"id":"bf888854ced8cc1e","repo":"jdx/mise","slug":"expected-exactly-one-manifest-in-index-json","errorCode":null,"errorMessage":"{}: expected exactly one manifest in index.json","messagePattern":"(.+?): expected exactly one manifest in index\\.json","errorType":"exception","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"src/oci/docker_archive.rs","lineNumber":46,"sourceCode":"    #[serde(rename = \"Config\")]\n    config: String,\n    #[serde(rename = \"RepoTags\")]\n    repo_tags: Vec<String>,\n    #[serde(rename = \"Layers\")]\n    layers: Vec<String>,\n}\n\n/// Stream the OCI layout at `image_dir` into `docker load`, tagging the\n/// loaded image as `tag`.\npub(crate) fn load_into_docker(image_dir: &Path, tag: &str) -> Result<()> {\n    let layout = ImageLayout {\n        root: image_dir.to_path_buf(),\n    };\n    let index_bytes = crate::file::read(image_dir.join(\"index.json\"))?;\n    let index: ImageIndex = serde_json::from_slice(&index_bytes).wrap_err(\"parsing index.json\")?;\n    let manifest_desc = match index.manifests.as_slice() {\n        [one] => one,\n        _ => bail!(\n            \"{}: expected exactly one manifest in index.json\",\n            image_dir.display()\n        ),\n    };\n    let manifest_bytes = layout.read_blob(&manifest_desc.digest)?;\n    let manifest: ImageManifest =\n        serde_json::from_slice(&manifest_bytes).wrap_err(\"parsing image manifest blob\")?;\n    let config_bytes = layout.read_blob(&manifest.config.digest)?;\n\n    // Validate every layer digest before it's used as a path component in\n    // `write_docker_archive` (which reads via `blob_path`, bypassing the\n    // check `read_blob` performs) — a crafted `--image-dir` layout could\n    // otherwise escape the blobs directory with `sha256:../…`.\n    for layer in &manifest.layers {\n        crate::oci::layout::validate_sha256_digest(&layer.digest)?;\n    }\n\n    let mut command = Command::new(\"docker\");","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/src/oci/docker_archive.rs#L28-L64","documentation":"`mise oci run` streams the built OCI layout into `docker load` (src/cli/oci/run.rs → load_into_docker). It reads `index.json` and expects exactly one manifest descriptor; zero or multiple manifests (e.g. a manifest list / multi-arch index written by other tooling) abort the load (src/oci/docker_archive.rs:46).","triggerScenarios":"Pointing `mise oci run` (or any load_into_docker path) at an `--image-dir` that was not produced by `mise oci build`: a layout exported by skopeo/umoci containing several images, an OCI image index (manifest list), or an emptied/garbled index.json.","commonSituations":"Reusing an image dir that other tooling wrote into; copying only part of a layout; passing the wrong directory (e.g. the parent containing several layout dirs).","solutions":["Rebuild the layout with `mise oci build` and point `--image-dir` at that output","If the layout is foreign, flatten it first: extract/split so index.json references exactly one (non-index) manifest","Verify before running: `jq '.manifests | length' <image-dir>/index.json` must be 1 and its mediaType an image manifest, not an index"],"exampleFix":"# before\nmise oci run --image-dir ./layouts/multi   # index.json with 3 manifests\n# after\njq '.manifests | length' ./mise-oci/index.json   # -> 1\nmise oci run --image-dir ./mise-oci","handlingStrategy":"validation","validationCode":"#!/usr/bin/env bash\nd=\"./mise-oci\"\nn=$(jq '.manifests | length' \"$d/index.json\")\nmt=$(jq -r '.manifests[0].mediaType' \"$d/index.json\")\n[ \"$n\" = \"1\" ] || { echo \"expected 1 manifest, got $n\" >&2; exit 1; }\n[ \"$mt\" = \"application/vnd.oci.image.manifest.v1+json\" ] || { echo \"not an image manifest: $mt\" >&2; exit 1; }\nmise oci run --image-dir \"$d\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only feed `mise oci run` image dirs produced by `mise oci build`","When exporting layouts with skopeo, copy a single platform manifest, not an index"],"tags":["oci","docker","image-layout","index-json"],"backgroundTag":"oci-layout-invalid","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}