jdx/mise · error · eyre::Report

artifactbundle = false conflicts with spm.artifactbundle_onl

Error message

artifactbundle = false conflicts with spm.artifactbundle_only

What it means

should_try_artifactbundle rejects a combination where the per-tool option says `artifactbundle = false` (SourceOnly) while the global `spm.artifactbundle_only` setting demands bundles for every spm install. The two directives contradict each other, so mise fails fast instead of guessing which wins.

Source

Thrown at src/backend/spm.rs:642

fn package_revision(tv: &ToolVersion) -> Option<PackageRevision> {
    match &tv.request {
        ToolRequest::Ref { ref_, ref_type, .. } if matches!(ref_type.as_str(), "ref" | "rev") => {
            Some(PackageRevision::Git(ref_.clone()))
        }
        _ => None,
    }
}

fn should_try_artifactbundle(
    revision: &PackageRevision,
    opts: &SpmOptions<'_>,
    mode: ArtifactBundleMode,
    artifactbundle_only: bool,
    display_version: &str,
) -> eyre::Result<bool> {
    if mode == ArtifactBundleMode::SourceOnly && artifactbundle_only {
        bail!("artifactbundle = false conflicts with spm.artifactbundle_only");
    }
    if revision.is_git_revision() && (opts.requires_artifactbundle(mode) || artifactbundle_only) {
        bail!(
            "SwiftPM artifact bundles require a release version; {display_version} selects a Git revision and must be built from source"
        );
    }
    Ok(!revision.is_git_revision() && mode != ArtifactBundleMode::SourceOnly)
}

fn with_install_env(mut command: Expression, tv: &ToolVersion) -> Expression {
    for (key, value) in tv.install_env() {
        command = match value.into_string() {
            Some(value) => command.env(key, value),
            None => command.env_remove(key),
        };
    }
    command
}

View on GitHub (pinned to 6f52dcdf99)

Solutions

  1. Remove `artifactbundle = false` from the tool entry (policy wins; the tool gets bundles or fails)
  2. Turn off the global `spm.artifactbundle_only` setting and enforce bundles per-tool with `artifactbundle = true`
  3. If you need per-tool escape hatches, model them as per-tool `artifactbundle = true` entries under a default-on policy that is not global

Example fix

# before
[settings.spm]
artifactbundle_only = true

[tools."spm:foo/bar"]
version = "1.0.0"
artifactbundle = false

# after
[settings.spm]
artifactbundle_only = true

[tools."spm:foo/bar"]
version = "1.0.0"
Defensive patterns

Strategy: validation

Validate before calling

mise settings get spm.artifactbundle_only | grep -q true && grep -Rn 'artifactbundle[[:space:]]*=[[:space:]]*false' mise.toml *.toml 2>/dev/null && echo 'conflict with artifactbundle_only'

Type guard

fn no_source_only_under_policy(tool: &toml::Value, policy_on: bool) -> bool {
    !(policy_on && tool.get("artifactbundle").and_then(|v| v.as_str()) == Some("false"))
}

Prevention

When it happens

Trigger: A global `[settings.spm] artifactbundle_only = true` plus one tool entry with `artifactbundle = false` to opt that tool into source builds. The conflict check runs before any install attempt.

Common situations: Trying to exempt a single misbehaving package from a team-wide bundles-only policy.

Related errors


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