jdx/mise · error

ambiguous variants for

Error message

ambiguous variants for {}

What it means

`tracking` evaluates each enrollment entry against the active environments using the variant selector. If the selector returns `Selection::Ambiguous`, more than one variant matches the current environments and the tool cannot determine which variant's state applies, so it aborts with the enrollment path.

Solutions

  1. Make the variant matchers mutually exclusive so exactly one matches the active environments
  2. Remove or merge the duplicate/overlapping variant in the enrollment entry
  3. Use the tool's variant validation (super::select::validate) or a lint step on the manifest before syncing
  4. Check the selection error detail (`Ambiguous(_)` payload) to see which variants collided

Example fix

// before
variants: [{name:"laptop", when: host=="x"}, {name:"dev", when: host=="x"}]
// after
variants: [{name:"laptop", when: host=="x"}] // or differentiate `when` clauses
Defensive patterns

Strategy: validation

Validate before calling

fn has_ambiguous_variants(entry: &Enrollment, envs: &Environments) -> bool {
  matches!(select::select(&entry.variants, envs), select::Selection::Ambiguous(_))
}

Try / catch

match manifest.tracking(&envs) {
  Err(e) if e.to_string().starts_with("ambiguous variants") => {
    eprintln!("fix overlapping variant matchers: {e}");
  }
  other => other,
}

Prevention

When it happens

Trigger: Calling `tracking` when an enrollment entry's `variants` list contains two or more variants whose environment predicates both match the current set of environments (e.g. overlapping matchers like two variants both matching the same hostname/OS).

Common situations: Hand-edited manifest with duplicate or overlapping variant conditions; adding a new variant that accidentally overlaps an existing one; a manifest synced from another machine with different variant rules.

Related errors


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

Appendix: source

Thrown at src/system/history/manifest.rs:253

    /// Restore enrollment from Git without needing a captured mise config.
    /// Deployment inputs are validated separately; none are inferred here.
    pub(crate) fn tracking(&self) -> Result<super::tracked::TrackedSet> {
        self.validate()?;
        let roots = super::sync::layout::Roots::current();
        let environments = super::select::active_environments();
        let mut tracked = super::tracked::TrackedSet {
            manifest: self.clone(),
            exclude: self.exclude.clone(),
            ..Default::default()
        };
        for enrollment in &self.enrollment {
            let variant = match super::select::select(&enrollment.variants, &environments) {
                super::select::Selection::Single => None,
                super::select::Selection::Variant(variant) => Some(variant.name()),
                super::select::Selection::NoMatch => continue,
                super::select::Selection::Ambiguous(_) => {
                    bail!("ambiguous variants for {}", enrollment.path)
                }
            };
            let local = roots
                .locate(&enrollment.path)
                .path()
                .ok_or_else(|| eyre::eyre!("invalid enrollment path {}", enrollment.path))?
                .to_path_buf();
            super::tracked::ensure_portable_ancestors(&local)?;
            let mut policy =
                crate::system::files::FilePolicy::for_mode(crate::system::files::FileMode::Track);
            policy.autosave = enrollment.autosave;
            policy.encrypt = enrollment.encrypt;
            let mut entry = super::tracked::TrackedEntry::new(local, "track", policy);
            entry.variant = variant;
            tracked.entries.push(entry);
        }
        Ok(tracked)
    }

View on GitHub (pinned to 533346cc37)