jdx/mise · error
mise oci requires an
Error message
mise oci requires an {}-based base image when [bootstrap.packages] contains {} entries; `scratch` has no {} metadata What it means
When `[bootstrap.packages]` entries exist, mise builds a system-packages layer by inspecting the base image's metadata (os release / package manager info). With a `scratch` (layerless) base image there are no layers to inspect, so mise cannot determine the target distro and aborts with this error naming the requested package manager.
Solutions
- Use a distro base image (e.g. alpine for apk, debian/ubuntu for apt) instead of scratch
- Remove the `[bootstrap.packages]` entries if you truly want a from-scratch image
- Bake the packages into your own base image and reference it
Example fix
// before (mise.toml) [bootstrap] from = "scratch" [bootstrap.packages] apt = ["curl"] // after [bootstrap] from = "debian:bookworm" [bootstrap.packages] apt = ["curl"]
Defensive patterns
Strategy: validation
Validate before calling
# shell check before build grep -q '^from = "scratch"' mise.toml && grep -q 'bootstrap.packages' mise.toml \ && echo "invalid: packages require a distro base image" || true
Try / catch
if let Err(e) = build_result {
if e.to_string().contains("`scratch` has no") {
eprintln!("switch [bootstrap] from to a distro image or drop [bootstrap.packages]");
}
} Prevention
- Never combine from = "scratch" with [bootstrap.packages]
- Keep a lint step validating bootstrap config before builds
- Prefer slim distro bases (alpine, debian-slim) when you need packages
- Review base-image changes after copying configs between projects
When it happens
Trigger: Running `mise oci build`/bootstrap where `[bootstrap.packages]` in the config has apt or apk entries but the base image resolves to scratch (no `base_layers`), so `build_system_packages_layer` has no metadata to work with.
Common situations: Building from scratch to keep images small while still asking for system packages; copying a mise.toml that installs packages into a config whose FROM was changed to scratch.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- mise oci currently supports only apt and apk entries in…
- [dotfiles]." ": mode symlink-each requires a directory…
- [dotfiles]." ": source does not exist
- [dotfiles]." ": source does not exist
- mise oci cannot mix apk and apt entries in…
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/8a4acf0546e2c69e.
Report an issue: GitHub.
Appendix: source
Thrown at src/oci/packages.rs:73
fn name(self) -> &'static str {
match self {
Self::Apk => "apk",
Self::Apt => "apt",
}
}
}
pub(crate) fn build_system_packages_layer(
layout: &ImageLayout,
base_layers: &[Descriptor],
managers: &[ManagerPackages],
architecture: &str,
) -> Result<Option<SystemPackagesLayer>> {
let Some((manager, requests)) = collect_package_requests(managers)? else {
return Ok(None);
};
if base_layers.is_empty() {
bail!(
"mise oci requires an {}-based base image when [bootstrap.packages] contains {} \
entries; `scratch` has no {} metadata",
manager.name(),
manager.name(),
manager.name(),
);
}
validate_host_requirements(manager)?;
let td = TempDir::with_prefix(format!("mise-oci-{}-rootfs-", manager.name())).wrap_err_with(
|| {
format!(
"creating temp rootfs for {} system packages",
manager.name()
)
},
)?;
let rootfs = td.path().join("rootfs");View on GitHub (pinned to 533346cc37)