jdx/mise · error

variants allow only one default, without os or profile selec

Error message

variants allow only one default, without os or profile selectors

What it means

validate rejects variant fallback lists where selector-bearing rules would be silently shadowed: there must be at most one default variant, and the default must not carry an os or profile selector, because defaults are only consulted when nothing matches and such selectors would never be honored.

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 afd2eddd3a)

Solutions

  1. Keep exactly one default variant with empty os and no profile
  2. Turn selector-bearing entries into non-default variants with explicit os/profile selectors
  3. Remove default: true from duplicates so only one fallback remains

Example fix

// before
variants = [
  { default = true, os = "linux" },
  { default = true }
]
// after
variants = [
  { os = "linux", version = "..." },
  { default = true }
]
Defensive patterns

Strategy: validation

Validate before calling

let defaults: Vec<_> = variants.iter().filter(|v| v.default).collect();
assert!(defaults.len() <= 1, "at most one default variant");
if let Some(d) = defaults.first() {
    assert!(d.os.is_empty() && d.profile.is_none(), "default must be unselected");
}

Prevention

When it happens

Trigger: Declaring two variants with default=true, or a single default variant with a non-empty os field or a Some(profile), in the variant list passed to validate.

Common situations: Copy-pasting a variant row and forgetting to clear default: true; adding os/profile to a fallback entry intending it to be conditional when it must be a plain default; merging config files that each defined a default.

Related errors


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