jdx/mise · error
invalid or repeated variant for
Error message
invalid or repeated variant for {} What it means
Variant names inside an enrollment entry must be safe branch path names, must not contain '@', and must be unique within the entry. `validate` bails when a variant name violates any of these rules, keeping variant names usable as branch/path components.
Solutions
- Rename the variant to a safe, unique branch-path-style name without '@' (e.g. use a hyphen instead of '@')
- Remove duplicate variant entries within the enrollment
- Validate variant names with the same rules you'd apply to file/branch names (no `..`, no separators/unsafe chars)
Example fix
// before variants = ["user@host", "laptop"] // after variants = ["user-host", "laptop"]
Defensive patterns
Strategy: validation
Validate before calling
fn variant_ok(name: &str, seen: &mut std::collections::BTreeSet<&str>) -> bool {
!name.contains('@') && is_safe_branch_path(name) && seen.insert(name)
} Try / catch
match manifest.validate() {
Err(e) if e.to_string().starts_with("invalid or repeated variant") => {
// rename/deduplicate variants, then re-validate
}
other => other,
} Prevention
- Avoid '@' and special characters in variant names; prefer [a-z0-9-]
- Ensure variant names are unique within each enrollment entry
- Lint manifests after copy/pasting or merging entries
When it happens
Trigger: Calling `validate` (via `tracking`, `write`, or permission capture) with an entry whose variant name contains '@', includes unsafe path characters or `..` segments, or repeats a name already used by another variant in the same entry.
Common situations: Naming variants with machine identifiers containing '@' (e.g. `user@host`); copy/pasting a variant and forgetting to rename it; using spaces or special characters in variant names.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- ambiguous variants for
- dotfile enrollment metadata must be a regular file
- firewall rule name ' ' must contain only ASCII letters…
- invalid bootstrap secret name
- invalid bootstrap service name
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/4a237cdd70d0ce5c.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/history/manifest.rs:378
let mut paths = std::collections::BTreeSet::new();
for entry in &self.enrollment {
if !super::sync::layout::is_safe_branch_path(&entry.path)
|| !(entry.path.starts_with("home/")
|| entry.path == "config"
|| entry.path.starts_with("config/"))
|| !paths.insert(&entry.path)
{
bail!("invalid or repeated enrollment path {}", entry.path);
}
let mut variants = std::collections::BTreeSet::new();
super::select::validate(&entry.variants)?;
for variant in &entry.variants {
let name = variant.name();
if name.contains('@')
|| !super::sync::layout::is_safe_branch_path(&name)
|| !variants.insert(name)
{
bail!("invalid or repeated variant for {}", entry.path);
}
}
}
for (path, bits) in &self.permissions {
if *bits > 0o777
|| !super::sync::layout::is_safe_branch_path(path)
|| !self.owns_stream(path)
{
bail!("invalid or unenrolled permission path {path}");
}
}
Ok(())
}
pub(crate) fn read(repo: &HistoryRepo, tree: &str) -> Result<Option<Self>> {
let Some((mode, oid)) = repo.object_at(tree, PATH)? else {
return Ok(None);
};View on GitHub (pinned to 533346cc37)