{"record":{"id":"bacf88014526ff65","repo":"jdx/mise","slug":"mise-oci-build-does-not-support-asdf-vfox-plugins-bacf88","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: {bad.join}","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":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/oci/builder.rs","lineNumber":1139,"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":1121,"sourceCodeEnd":1157,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/oci/builder.rs#L1121-L1157","documentation":"mise's `oci build` supports only backends whose installation is confined to a per-version directory, because each tool becomes its own OCI layer. asdf and vfox plugin install scripts can write arbitrary files outside that directory, so build fails fast when any requested tool uses such a backend, listing the affected tools.","triggerScenarios":"Running `mise oci build` where the resolved toolset includes any tool whose backend short name is asdf or vfox (e.g. an asdf-installed plugin like `asdf:some/plugin`); reject_unsupported_backends collects these and bails before layer building.","commonSituations":"Migrating an existing toolset that still relies on legacy asdf plugins or vfox plugins to OCI image building; a registry entry resolving to an asdf backend unintentionally.","solutions":["Replace asdf/vfox-based tools in the toolset with native backends (core plugins, aqua:, github:, cargo:, npm:, etc.) before building the OCI image.","Check `mise ls --json` (or the tool resolution) to identify which tools use asdf/vfox backends, per the 'Affected tools' list in the message.","Install those tools with a supported backend, e.g. `mise use aqua:owner/repo` or `mise use github:owner/repo`, then rerun `mise oci build`."],"exampleFix":"// before (.mise.toml)\n[tools]\n\"asdf:nodejs\" = \"20\"\n// after\n[tools]\nnode = \"20\"","handlingStrategy":"validation","validationCode":"const UNSUPPORTED = [\"asdf\", \"vfox\"];\nfunction assertNoPluginBackends(tools) {\n  const bad = tools.filter(t => UNSUPPORTED.includes(t.backendShort));\n  if (bad.length) throw new Error(`oci build unsupported backends: ${bad.map(t => t.name).join(\", \")}`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  buildOciImage(tools);\n} catch (e) {\n  if (String(e).includes(\"asdf/vfox plugins\")) {\n    console.error(\"swap these tools to native/aqua/github backends first:\", e.message);\n    process.exit(1);\n  }\n  throw e;\n}","preventionTips":["Prefer core, aqua:, github:, cargo:, npm: backends over asdf/vfox plugins in images.","Audit `mise ls --json` for asdf/vfox backends before adding oci build to CI.","Pin tool sources in mise.toml so a registry change cannot silently switch a tool to an asdf backend."],"tags":["oci","asdf","vfox","unsupported-backend"],"backgroundTag":"unsupported-operation","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}