jdx/mise · error
variant target must be absolute or start with ~/
Error message
variant target must be absolute or start with ~/
What it means
Thrown by `validate_file_variants` when a variant's effective destination — its `target` override, or the entry's target when the variant has none — is not absolute (and does not start with `~/`). Every variant must resolve to an absolute destination; the check uses variant_target_is_absolute on the chosen destination.
Solutions
- Set each variant's `target` to an absolute path or one beginning with `~/`.
- If variants inherit the entry target, make the entry-level target absolute instead.
- Check any templated/interpolated target values for accidental emptiness or relative expansion.
Example fix
// before [[files.variants]] os = "linux" target = "config/git/config" // after [[files.variants]] os = "linux" target = "~/.config/git/config"
Defensive patterns
Strategy: validation
Validate before calling
for v in &entry.variants {
let dest = v.target.as_deref().unwrap_or(entry.target);
if !dest.starts_with("~/") && !Path::new(dest).is_absolute() {
bail!("variant target '{}' must be absolute or start with ~/", dest);
}
} Type guard
fn variant_dest_is_absolute(v: &FileVariant, entry_target: &str) -> bool {
let dest = v.target.as_deref().unwrap_or(entry_target);
dest.starts_with("~/") || Path::new(dest).is_absolute()
} Prevention
- Give every variant an absolute `~/`- or `/`-anchored target.
- If variants inherit the entry target, ensure that target is absolute.
- Check templated targets expand to non-empty absolute paths.
When it happens
Trigger: Any `[[files.variants]]` whose `target` is a relative path, or which inherits a relative entry-level `target` — checked per-variant in the `for variant in variants` loop after the no-variant case.
Common situations: Adding variants for OS-specific configs and writing short relative destinations; a template/variable expanding to an empty or relative string; copying the source file name into the variant target field.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- target must be absolute or start with ~/
- agent ' ' `start_calendar_interval. ` must be between and
- agent ' ' `start_calendar_interval` must set at least one…
- agent ' ' `start_calendar_interval` must not be empty
- agent ' ' `queue_directories` must not contain empty entries
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/b83f8829c24c2c2d.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/files.rs:238
bail!("destination variants with inline content are not supported");
}
let implied_source = if has_target_override && source.is_none() {
if !variants.iter().all(|v| v.target.is_some()) {
bail!(
"destination variants require an explicit source when any variant uses the entry key as its target"
);
}
Some(logical_source_path(target)?)
} else {
None
};
if variants.is_empty() && resolve_target_arg(target).is_relative() {
bail!("target must be absolute or start with ~/");
}
for variant in variants {
let destination = variant.target.as_deref().unwrap_or(target);
if !variant_target_is_absolute(destination) {
bail!("variant target must be absolute or start with ~/");
}
}
Ok(implied_source)
}
fn logical_source_path(key: &str) -> Result<PathBuf> {
let path = file::replace_path(key);
if !path.is_relative() {
bail!(
"destination variants require an explicit source unless the entry key is a relative source path"
);
}
let mut relative = PathBuf::new();
for component in path.components() {
match component {
std::path::Component::Normal(component) => relative.push(component),
std::path::Component::CurDir => {}
std::path::Component::ParentDir => {View on GitHub (pinned to 533346cc37)