jdx/mise · error

variants allow only one default, without os or profile…

Error message

variants allow only one default, without os or profile selectors

What it means

Variant selection resolves a fallback by matching os/profile selectors and otherwise using the single default. A default variant carrying os or profile selectors would never be selected the way the author expects, and more than one default is ambiguous, so validate rejects both at load time.

Solutions

  1. Keep exactly one default variant and remove os/profile selectors from it
  2. Move os/profile-specific behavior to non-default variants with matching selectors
  3. If multiple defaults were intentional, pick one and use selectors on the others

Example fix

# before
[[variants]]
default = true
os = "linux"
[[variants]]
default = true
# after
[[variants]]
default = true
[[variants]]
os = "linux"
Defensive patterns

Strategy: validation

Validate before calling

let defaults: Vec<_> = variants.iter().filter(|v| v.default).collect();
if defaults.len() != 1
    || defaults.iter().any(|v| !v.os.is_empty() || v.profile.is_some())
{
    eprintln!("config invalid: exactly one selector-free default variant required");
}

Try / catch

match variants::validate(&variants) {
    Err(e) if e.to_string().contains("only one default") => {
        eprintln!("fix variants config: one default, no os/profile on the default");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Defining a variants list where (a) two or more variants set default = true, or (b) a default variant also sets a non-empty os selector or a Some(profile) selector.

Common situations: Config authoring mistakes: duplicating a default when adding platform-specific variants; marking a linux-only variant as default; copy-pasting a selector-qualified variant and adding default = true.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/cfacdbf831d24722. Report an issue: GitHub.

Appendix: source

Thrown at src/system/history/select.rs:92

#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) enum Selection {
    /// The entry has no variants: one stream for every machine.
    Single,
    /// The variant this machine uses.
    Variant(Variant),
    /// No variant matches and none is the default: do not capture or apply.
    NoMatch,
    /// Two variants match with the same specificity.
    Ambiguous(Vec<Variant>),
}

/// Reject fallbacks whose selectors would be ignored during selection.
pub(crate) fn validate(variants: &[Variant]) -> eyre::Result<()> {
    let mut default_seen = false;
    for variant in variants {
        if variant.default {
            if default_seen || !variant.os.is_empty() || variant.profile.is_some() {
                eyre::bail!("variants allow only one default, without os or profile selectors");
            }
            default_seen = true;
        }
    }
    Ok(())
}

/// Picks the variant for this machine given the active mise environments.
pub(crate) fn select(variants: &[Variant], environments: &[String]) -> Selection {
    if variants.is_empty() {
        return Selection::Single;
    }
    let matching: Vec<&Variant> = variants
        .iter()
        .filter(|variant| !variant.default && variant.matches(environments))
        .collect();
    let best = matching.iter().map(|variant| variant.specificity()).max();
    match best {

View on GitHub (pinned to 533346cc37)