{"record":{"id":"e86fb10cebaa444f","repo":"jdx/mise","slug":"ambiguous-variants-for","errorCode":null,"errorMessage":"ambiguous variants for {}","messagePattern":"ambiguous variants for (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/history/manifest.rs","lineNumber":253,"sourceCode":"\n    /// Restore enrollment from Git without needing a captured mise config.\n    /// Deployment inputs are validated separately; none are inferred here.\n    pub(crate) fn tracking(&self) -> Result<super::tracked::TrackedSet> {\n        self.validate()?;\n        let roots = super::sync::layout::Roots::current();\n        let environments = super::select::active_environments();\n        let mut tracked = super::tracked::TrackedSet {\n            manifest: self.clone(),\n            exclude: self.exclude.clone(),\n            ..Default::default()\n        };\n        for enrollment in &self.enrollment {\n            let variant = match super::select::select(&enrollment.variants, &environments) {\n                super::select::Selection::Single => None,\n                super::select::Selection::Variant(variant) => Some(variant.name()),\n                super::select::Selection::NoMatch => continue,\n                super::select::Selection::Ambiguous(_) => {\n                    bail!(\"ambiguous variants for {}\", enrollment.path)\n                }\n            };\n            let local = roots\n                .locate(&enrollment.path)\n                .path()\n                .ok_or_else(|| eyre::eyre!(\"invalid enrollment path {}\", enrollment.path))?\n                .to_path_buf();\n            super::tracked::ensure_portable_ancestors(&local)?;\n            let mut policy =\n                crate::system::files::FilePolicy::for_mode(crate::system::files::FileMode::Track);\n            policy.autosave = enrollment.autosave;\n            policy.encrypt = enrollment.encrypt;\n            let mut entry = super::tracked::TrackedEntry::new(local, \"track\", policy);\n            entry.variant = variant;\n            tracked.entries.push(entry);\n        }\n        Ok(tracked)\n    }","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/history/manifest.rs#L235-L271","documentation":"`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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Make the variant matchers mutually exclusive so exactly one matches the active environments","Remove or merge the duplicate/overlapping variant in the enrollment entry","Use the tool's variant validation (super::select::validate) or a lint step on the manifest before syncing","Check the selection error detail (`Ambiguous(_)` payload) to see which variants collided"],"exampleFix":"// before\nvariants: [{name:\"laptop\", when: host==\"x\"}, {name:\"dev\", when: host==\"x\"}]\n// after\nvariants: [{name:\"laptop\", when: host==\"x\"}] // or differentiate `when` clauses","handlingStrategy":"validation","validationCode":"fn has_ambiguous_variants(entry: &Enrollment, envs: &Environments) -> bool {\n  matches!(select::select(&entry.variants, envs), select::Selection::Ambiguous(_))\n}","typeGuard":null,"tryCatchPattern":"match manifest.tracking(&envs) {\n  Err(e) if e.to_string().starts_with(\"ambiguous variants\") => {\n    eprintln!(\"fix overlapping variant matchers: {e}\");\n  }\n  other => other,\n}","preventionTips":["Keep variant matchers mutually exclusive per entry","Run manifest validation/lint in CI before syncing","Review the Ambiguous payload to see exactly which variants overlap"],"tags":["manifest","variants","ambiguity","config"],"backgroundTag":"ambiguous-match","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}