{"record":{"id":"cca9a8dbb3efd71b","repo":"jdx/mise","slug":"index-json-lists-manifests-multi-manifest","errorCode":null,"errorMessage":"{}: index.json lists {} manifests; multi-manifest layouts are not supported","messagePattern":"(.+?): index\\.json lists (.+?) manifests; multi-manifest layouts are not supported","errorType":"exception","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"src/oci/registry.rs","lineNumber":932,"sourceCode":"    update_index: bool,\n) -> Result<PushSummary> {\n    eyre::ensure!(\n        !crate::config::Settings::get().offline(),\n        \"offline mode is enabled\"\n    );\n    let r = Reference::parse(reference)?;\n    let layout = ImageLayout {\n        root: image_dir.to_path_buf(),\n    };\n\n    // Resolve the layout's single manifest. `mise oci build` always writes\n    // exactly one manifest into index.json.\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!(\"{}: index.json lists no manifests\", image_dir.display()),\n        many => bail!(\n            \"{}: index.json lists {} manifests; multi-manifest layouts are not supported\",\n            image_dir.display(),\n            many.len()\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\n    // Cross-repo mount source: the base image's repository, when it lives on\n    // the destination registry (and isn't the destination repo itself).\n    let mount_from = manifest\n        .annotations\n        .get(ANNOTATION_BASE_NAME)\n        .and_then(|name| Reference::parse(name).ok())\n        .filter(|base| base.registry == r.registry && base.repository != r.repository)\n        .map(|base| base.repository);\n","sourceCodeStart":914,"sourceCodeEnd":950,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/oci/registry.rs#L914-L950","documentation":"Same layout reader as the empty-index case, but here index.json lists more than one manifest. mise only supports pushing single-manifest layouts (one platform); a multi-manifest index — such as a multi-platform bundle from `docker buildx --output type=oci`, ORAS, or hand-merged layouts — is rejected because push cannot decide which manifest represents the image.","triggerScenarios":"Pushing a layout directory produced by external multi-platform tooling, or one mutated by appending manifests to index.json, instead of the layout written by `mise oci build`.","commonSituations":"Teams mixing docker buildx OCI exports with mise oci build outputs in one artifacts dir; hand-assembling multi-arch indexes then trying to push via mise.","solutions":["Push the layout produced by `mise oci build` for a single platform — do not point mise at buildx/ORAS multi-platform exports","Build one platform at a time so each layout keeps exactly one manifest","Use `crane push`/`oras push` for hand-assembled or multi-manifest layouts; use mise oci push for mise-built layouts"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Reject multi-manifest layouts before push (same guard, count > 1).\nfn layout_manifest_count(image_dir: &Path) -> usize {\n    std::fs::read(image_dir.join(\"index.json\"))\n        .ok()\n        .and_then(|b| serde_json::from_slice::<serde_json::Value>(&b).ok())\n        .and_then(|v| v[\"manifests\"].as_array().map(|a| a.len()))\n        .unwrap_or(0)\n}\n\nif layout_manifest_count(&image_dir) != 1 {\n    anyhow::bail!(\"push needs a single-manifest mise-built layout\");\n}","typeGuard":"fn is_single_manifest_layout(image_dir: &Path) -> bool {\n    layout_manifest_count(image_dir) == 1\n}","tryCatchPattern":null,"preventionTips":["Keep one platform per layout directory; never merge buildx/ORAS outputs into a mise image dir","Push multi-platform bundles with crane/oras, reserve mise oci push for mise-built layouts"],"tags":["mise","oci","push","image-layout","index-json","multi-arch"],"backgroundTag":"oci-image-layout-invalid","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}