{"record":{"id":"df67f2d1294a3b81","repo":"jdx/mise","slug":"mise-oci-build-does-not-support-asdf-vfox-plugins","errorCode":null,"errorMessage":"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: {}","messagePattern":"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: (.+?)","errorType":"validation","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"src/oci/builder.rs","lineNumber":1122,"sourceCode":"fn reject_unsupported_backends(\n    versions: &[(Arc<dyn crate::backend::Backend>, ToolVersion)],\n) -> Result<()> {\n    // Ask the actual backend instance rather than parsing the short name.\n    // `BackendType::guess` only matches literal \"asdf\" / \"vfox\" prefixes and\n    // misses third-party vfox plugins whose tools use a custom plugin name\n    // as the prefix (e.g. `my-plugin:tool`), even though they have the same\n    // out-of-tree write behavior we're guarding against.\n    let bad: Vec<String> = versions\n        .iter()\n        .filter_map(|(backend, tv)| match backend.get_type() {\n            BackendType::Asdf | BackendType::Vfox | BackendType::VfoxBackend(_) => {\n                Some(tv.ba().short.clone())\n            }\n            _ => None,\n        })\n        .collect();\n    if !bad.is_empty() {\n        bail!(\n            \"mise oci build does not support asdf/vfox plugins in v1 (their install scripts can \\\n             write outside the per-version directory, breaking the one-layer-per-tool invariant). \\\n             Affected tools: {}\",\n            bad.join(\", \")\n        );\n    }\n    Ok(())\n}\n\n/// Rewrite any occurrence of the host install path in an `exec_env` value to\n/// the corresponding in-image path. Handles both exact matches\n/// (`JAVA_HOME=<install>`) and colon-separated PATH-like values\n/// (`SOMETHING=<install>/foo:<install>/bar`).\nfn rebase_path_value(value: &str, host_prefix: &std::path::Path, in_image_prefix: &str) -> String {\n    let host: &str = &host_prefix.to_string_lossy();\n    if host.is_empty() || !value.contains(host) {\n        return value.to_string();\n    }","sourceCodeStart":1104,"sourceCodeEnd":1140,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/src/oci/builder.rs#L1104-L1140","documentation":"`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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["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","Remove or comment out the affected tools from the config used for `mise oci build`","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)"],"exampleFix":"# before (asdf plugin tool)\nmise use erlang@26   # via asdf plugin -> rejected\n# after (core/backend tool)\nmise use erlang@26 --backend core   # or use an aqua: backend tool","handlingStrategy":"validation","validationCode":"#!/usr/bin/env bash\n# Fail if any current tool resolves through an asdf/vfox plugin backend\nbad=$(mise ls --current --json 2>/dev/null | jq -r '.[] | select(.backend == \"asdf\" or .backend == \"vfox\") | .name' | sort -u)\n[ -z \"$bad\" ] || { echo \"oci build rejects plugin tools: $bad\" >&2; exit 1; }\nmise oci build","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer core, aqua:, or github: backends for tools that must ship in images","Maintain a separate OCI-scoped mise.toml without plugin tools"],"tags":["oci","asdf","vfox","plugins","unsupported"],"backgroundTag":"unsupported-tool-backend","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}