jdx/mise · error

podman pull succeeded but printed no image ID

Error message

podman pull succeeded but printed no image ID

What it means

mise identifies the loaded image by parsing the trimmed stdout of `podman pull --quiet` as an image ID (deterministic across podman versions, per the code comment). If the command exits 0 but stdout is empty, mise cannot construct the `podman run <id>` invocation or the later `podman rmi` cleanup, so it bails rather than guessing.

Source

Thrown at src/cli/oci/run.rs:283

fn load_image(engine: Engine, image_dir: &Path) -> Result<String> {
    match engine {
        Engine::Podman => {
            let src = format!("oci:{}", image_dir.display());
            let out = Command::new("podman")
                .args(["pull", "--quiet", &src])
                .output()
                .wrap_err("running `podman pull`")?;
            if !out.status.success() {
                let stderr = String::from_utf8_lossy(&out.stderr);
                bail!("podman pull failed: {}: {stderr}", out.status);
            }
            // `podman pull --quiet` prints just the image ID on stdout.
            let id = String::from_utf8(out.stdout)
                .wrap_err("podman pull produced non-utf8 output")?
                .trim()
                .to_string();
            if id.is_empty() {
                bail!("podman pull succeeded but printed no image ID");
            }
            Ok(id)
        }
        Engine::Docker => {
            // Stream the layout into `docker load` as a docker-archive. Pick
            // a per-invocation tag so concurrent `mise oci run` calls don't
            // clobber each other — a shared `mise-oci:run` tag would
            // otherwise race: the second load would overwrite the first
            // image before the first container started.
            let tag = format!(
                "mise-oci:run-{}-{}",
                std::process::id(),
                std::time::SystemTime::now()
                    .duration_since(std::time::UNIX_EPOCH)
                    .map(|d| d.as_nanos())
                    .unwrap_or(0)
            );
            crate::oci::docker_archive::load_into_docker(image_dir, &tag)?;

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Manually verify what your podman prints: `podman pull --quiet oci:<dir>` — if empty, upgrade/downgrade podman
  2. Switch engines: `mise oci run --engine docker ...` (docker path loads a docker-archive with a tag instead)
  3. Report the podman version to the mise issue tracker if a stock podman reproduces it

Example fix

# before
mise oci run --engine podman ghcr.io/you/devenv:tag -- bash
# after
mise oci run --engine docker ghcr.io/you/devenv:tag -- bash
Defensive patterns

Strategy: fallback

Validate before calling

# bash: probe that podman prints an ID for --quiet pulls before relying on it
test_id=$(podman pull --quiet "oci:$dir" 2>/dev/null || true)
if [ -z "$test_id" ]; then ENGINE_ARG="--engine docker"; fi
mise oci run $ENGINE_ARG -- bash

Prevention

When it happens

Trigger: A podman version/configuration where `pull --quiet` prints the ID to stderr or nowhere (e.g. JSON log driver redirecting output, odd TTY handling, patched distro podman); stdout consumed by wrappers that capture fds.

Common situations: Distro-patched or very new podman builds changing --quiet output behavior; running under process supervisors that capture/redirect the child's stdout; containers with a redirected podman log destination.

Related errors


AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17). Data as JSON: /api/errors/3e92f1e098c23e0a. Report an issue: GitHub.