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
- Keep exactly one default variant with empty os and no profile
- Turn selector-bearing entries into non-default variants with explicit os/profile selectors
- 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
- Only mark plain fallback entries as default
- Give every os/profile-specific variant an explicit selector and default=false
- Lint variant tables after merging config files
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
- managed path '{}' notifies unconfigured bootstrap service '{
- managed path '{}' notifies unconfigured bootstrap service '{
- cask uses `#{feature}`, which mise's cask shim does not supp
- formula uses `#{feature}`, which mise's source-build shim do
- windows_script_interpreter: {interpreter:?} must be a plain
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/cfacdbf831d24722.
Report an issue: GitHub.