jdx/mise · error · eyre::Report

mise oci build does not support asdf/vfox plugins in v1 (the

Error message

mise oci build does not support asdf/vfox plugins in v1 (their install scripts can write outside the per-version directory, breaking the one-layer-per-tool invariant). Affected tools: {}

What it means

`mise oci build` v1 packs each tool as exactly one layer from its per-version install directory. asdf and vfox plugin install scripts may write outside that directory, breaking the one-layer-per-tool invariant, so any resolved tool backed by those backend types is rejected up front with the affected tool names listed (src/oci/builder.rs:1122).

Source

Thrown at src/oci/builder.rs:1122

fn reject_unsupported_backends(
    versions: &[(Arc<dyn crate::backend::Backend>, ToolVersion)],
) -> Result<()> {
    // Ask the actual backend instance rather than parsing the short name.
    // `BackendType::guess` only matches literal "asdf" / "vfox" prefixes and
    // misses third-party vfox plugins whose tools use a custom plugin name
    // as the prefix (e.g. `my-plugin:tool`), even though they have the same
    // out-of-tree write behavior we're guarding against.
    let bad: Vec<String> = versions
        .iter()
        .filter_map(|(backend, tv)| match backend.get_type() {
            BackendType::Asdf | BackendType::Vfox | BackendType::VfoxBackend(_) => {
                Some(tv.ba().short.clone())
            }
            _ => None,
        })
        .collect();
    if !bad.is_empty() {
        bail!(
            "mise oci build does not support asdf/vfox plugins in v1 (their install scripts can \
             write outside the per-version directory, breaking the one-layer-per-tool invariant). \
             Affected tools: {}",
            bad.join(", ")
        );
    }
    Ok(())
}

/// Rewrite any occurrence of the host install path in an `exec_env` value to
/// the corresponding in-image path. Handles both exact matches
/// (`JAVA_HOME=<install>`) and colon-separated PATH-like values
/// (`SOMETHING=<install>/foo:<install>/bar`).
fn rebase_path_value(value: &str, host_prefix: &std::path::Path, in_image_prefix: &str) -> String {
    let host: &str = &host_prefix.to_string_lossy();
    if host.is_empty() || !value.contains(host) {
        return value.to_string();
    }

View on GitHub (pinned to 6f52dcdf99)

Solutions

  1. Replace the plugin-backed tool with an equivalent core/aqua/github-backed one (e.g. `mise use aqua:<owner>/<repo>` or a core plugin) for the image build
  2. Remove or comment out the affected tools from the config used for `mise oci build`
  3. Keep the plugin tools for local dev but build the image from a scoped config (`mise --config ./mise.oci.toml oci build` or a separate project dir)

Example fix

# before (asdf plugin tool)
mise use erlang@26   # via asdf plugin -> rejected
# after (core/backend tool)
mise use erlang@26 --backend core   # or use an aqua: backend tool
Defensive patterns

Strategy: validation

Validate before calling

#!/usr/bin/env bash
# Fail if any current tool resolves through an asdf/vfox plugin backend
bad=$(mise ls --current --json 2>/dev/null | jq -r '.[] | select(.backend == "asdf" or .backend == "vfox") | .name' | sort -u)
[ -z "$bad" ] || { echo "oci build rejects plugin tools: $bad" >&2; exit 1; }
mise oci build

Prevention

When it happens

Trigger: Running `mise oci build` when mise.toml (or global config) resolves tools whose backend type is Asdf or Vfox — e.g. `mise use ubi://`-style alternatives aside, an asdf plugin like `mise use erlang@main` via an asdf plugin, or a vfox-plugin-backed tool.

Common situations: Teams with mixed setups where some members install tools via asdf plugins; inheriting a global mise config containing plugin tools when trying the new oci build feature.

Related errors


AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22). Data as JSON: /api/errors/df67f2d1294a3b81. Report an issue: GitHub.