jdx/mise · error · eyre::Report

mise oci found apt packages in [bootstrap.packages], but the

Error message

mise oci found apt packages in [bootstrap.packages], but the base image does not contain /etc/apt. Use a Debian/Ubuntu base image or remove the apt entries.

What it means

prepare_apt_install checks that the unpacked base image rootfs contains /etc/apt before running apt-get against it. `[bootstrap.packages]` collected apt entries, but the base image is not Debian-based, so apt-get could not operate on that rootfs — mise aborts with explicit guidance instead of producing a broken layer.

Source

Thrown at src/oci/packages.rs:334

    Ok(true)
}

fn remove_path(path: &Path) -> Result<()> {
    match fs::symlink_metadata(path).map(|m| m.file_type()) {
        Ok(ft) if ft.is_dir() && !ft.is_symlink() => fs::remove_dir_all(path)
            .wrap_err_with(|| format!("removing directory {}", path.display()))?,
        Ok(_) => fs::remove_file(path).wrap_err_with(|| format!("removing {}", path.display()))?,
        Err(e) if e.kind() == std::io::ErrorKind::NotFound => {}
        Err(e) => {
            return Err(e).wrap_err_with(|| format!("reading metadata for {}", path.display()));
        }
    }
    Ok(())
}

fn prepare_apt_install(rootfs: &Path) -> Result<()> {
    if !rootfs.join("etc/apt").is_dir() {
        bail!(
            "mise oci found apt packages in [bootstrap.packages], but the base image does not \
             contain /etc/apt. Use a Debian/Ubuntu base image or remove the apt entries."
        );
    }
    prepare_apt_rootfs(rootfs)
}

fn prepare_apk_install(rootfs: &Path) -> Result<()> {
    if !rootfs.join("etc/apk").is_dir() || !rootfs.join("lib/apk/db").is_dir() {
        bail!(
            "mise oci found apk packages in [bootstrap.packages], but the base image does not \
             contain an apk database. Use an Alpine/Wolfi base image or remove the apk entries."
        );
    }
    Ok(())
}

fn apk_install_into_rootfs(

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Change the base image to a Debian/Ubuntu one (debian:bookworm-slim, ubuntu:24.04) so /etc/apt exists
  2. Or convert the entries to `[bootstrap.packages.apk]` if the Alpine/minimal base must stay
  3. Remember `scratch` bases are rejected for any [bootstrap.packages] — a distro base with the matching package metadata is mandatory

Example fix

# before (mise.toml)
base_image = "alpine:3.20"
[bootstrap.packages.apt]
ripgrep = "any"

# after — base image matches apt
base_image = "debian:bookworm-slim"
[bootstrap.packages.apt]
ripgrep = "any"
Defensive patterns

Strategy: validation

Validate before calling

# Confirm the base image is Debian-based before configuring apt entries:
crane export debian:bookworm-slim - | tar -x etc/os-release -O 2>/dev/null \
  | grep -E 'ID=(debian|ubuntu)'
# If the grep fails, the base lacks /etc/apt — use apk entries or a Debian base.

Type guard

fn base_supports_apt(base_image: &str) -> bool {
    // Conservative allow-list of Debian-family bases
    ["debian:", "ubuntu:", "linuxserver/"]
        .iter()
        .any(|p| base_image.starts_with(p))
}

Prevention

When it happens

Trigger: `mise oci build` with `[bootstrap.packages.apt]` entries while the base image is `alpine:*`, `busybox`, `scratch`, or a non-Debian distroless/wolfi image — i.e. anything whose rootfs lacks /etc/apt.

Common situations: Switching the base image in config (e.g. for size) without converting the package table; starting from `scratch` or a minimal base and expecting apt bootstrap to work.

Related errors


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