jdx/mise · error · eyre::Report
{}: index.json lists no manifests
Error message
{}: index.json lists no manifests What it means
`mise oci push` reads the image layout directory produced by `mise oci build` and expects index.json to reference exactly one manifest. An empty manifests array means the layout has no image content — the documented contract ("build always writes exactly one manifest into index.json") is broken, so push refuses rather than upload nothing.
Source
Thrown at src/oci/registry.rs:931
reference: &str,
update_index: bool,
) -> Result<PushSummary> {
eyre::ensure!(
!crate::config::Settings::get().offline(),
"offline mode is enabled"
);
let r = Reference::parse(reference)?;
let layout = ImageLayout {
root: image_dir.to_path_buf(),
};
// Resolve the layout's single manifest. `mise oci build` always writes
// exactly one manifest into index.json.
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!("{}: index.json lists no manifests", image_dir.display()),
many => bail!(
"{}: index.json lists {} manifests; multi-manifest layouts are not supported",
image_dir.display(),
many.len()
),
};
let manifest_bytes = layout.read_blob(&manifest_desc.digest)?;
let manifest: ImageManifest =
serde_json::from_slice(&manifest_bytes).wrap_err("parsing image manifest blob")?;
// Cross-repo mount source: the base image's repository, when it lives on
// the destination registry (and isn't the destination repo itself).
let mount_from = manifest
.annotations
.get(ANNOTATION_BASE_NAME)
.and_then(|name| Reference::parse(name).ok())
.filter(|base| base.registry == r.registry && base.repository != r.repository)
.map(|base| base.repository);View on GitHub (pinned to 9dcfcaa0dc)
Solutions
- Re-run `mise oci build` to regenerate a complete layout, then push
- Make the push step conditional on build success in CI (fail-fast between jobs)
- Verify the layout before pushing: index.json's manifests array should list exactly one entry with a digest whose blob exists under blobs/
Defensive patterns
Strategy: validation
Validate before calling
// Validate the layout before invoking `mise oci push`.
fn layout_has_single_manifest(image_dir: &Path) -> Result<bool, String> {
let bytes = std::fs::read(image_dir.join("index.json")).map_err(|e| e.to_string())?;
let index: serde_json::Value = serde_json::from_slice(&bytes).map_err(|e| e.to_string())?;
let n = index["manifests"].as_array().map(|a| a.len()).unwrap_or(0);
Ok(n == 1)
}
if !layout_has_single_manifest(&image_dir)? {
anyhow::bail!("layout incomplete — re-run `mise oci build` before push");
} Type guard
fn is_pushable_layout(image_dir: &Path) -> bool {
std::fs::read(image_dir.join("index.json"))
.ok()
.and_then(|b| serde_json::from_slice::<serde_json::Value>(&b).ok())
.and_then(|v| v["manifests"].as_array().map(|a| a.len() == 1))
.unwrap_or(false)
} Prevention
- Gate the push CI step on build success (needs: build job / set -e in shared scripts)
- Never hand-edit the image directory between build and push
- Treat an empty manifests array as a corrupted artifact: regenerate, do not patch
When it happens
Trigger: Pointing push at an image directory whose build failed or was interrupted before the manifest was written; a hand-emptied or incorrectly copied layout directory; passing the wrong --image-dir path that happens to contain an empty index.json.
Common situations: Build and push split across CI jobs where the build job failed but push ran anyway; artifacts copied incomidentally (index.json copied, blobs dir not); manual tampering with the layout directory.
Related errors
- {}: index.json lists {} manifests; multi-manifest layouts ar
- {}: does not look like an OCI image layout (missing index.js
- fetching {manifest_url} failed: {}
- starting blob upload failed: {} {}{}
- blob chunk upload failed: {}{} {}
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/dd2da0d3fe71d7fe.
Report an issue: GitHub.