jdx/mise · error
an implied source entry key must not be empty
Error message
an implied source entry key must not be empty
What it means
If every component of the entry key is trivial (e.g. the key is `.`, `./`, or `~/` alone after expansion), the constructed relative source path is empty, which is not a valid file. `logical_source_path` rejects this rather than silently treating the dotfiles root as the source.
Solutions
- Replace the placeholder key with the actual relative source file path
- Add an explicit `source` field naming the file
- Remove the entry if it was accidental
Example fix
// before
"." = { variants = [ { target = "~/.zshrc" } ] }
// after
"~/.zshrc" = { source = "dotfiles/zshrc", variants = [ { target = "~/.zshrc" } ] } Defensive patterns
Strategy: validation
Validate before calling
function keyNormalizesToEmpty(key) {
const rel = key.replace(/^~\/?/, '').replace(/^[.\\/]+/, '');
return rel.length === 0;
} Type guard
const isNonEmptyRelativeKey = (key: string) => key.replace(/^[~.]\/?/, '').split(/[\\/]/).filter(c => c && c !== '.').length > 0;
Prevention
- Never use `.` or `~/` alone as an entry key
- Ensure every key names a concrete file or directory
When it happens
Trigger: Entry key that normalizes to nothing, such as `"."` or `"~/"`, combined with `variants` and no explicit `source`.
Common situations: Copy-paste mistakes leaving a placeholder key like `"."`, or trimming a key down while debugging and leaving it empty of real components.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- agent ' ' must set a non-empty `program
- an implied source entry key must be relative
- an implied source entry key must not contain '..'
- brew-cask: generate_completions_from_executable requires at…
- brew-cask: generate_completions_from_executable requires an…
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/bbceec5a1a3324c8.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/files.rs:265
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 => {
bail!("an implied source entry key must not contain '..'");
}
std::path::Component::RootDir | std::path::Component::Prefix(_) => {
bail!("an implied source entry key must be relative");
}
}
}
if relative.as_os_str().is_empty() {
bail!("an implied source entry key must not be empty");
}
Ok(relative)
}
/// Inactive variants can contain another platform's absolute path syntax.
/// The selected destination is still checked with native path rules before use.
fn variant_target_is_absolute(target: &str) -> bool {
let bytes = target.as_bytes();
resolve_target_arg(target).is_absolute()
|| target.starts_with('/')
|| target.starts_with("\\\\")
|| (bytes.len() >= 3
&& bytes[0].is_ascii_alphabetic()
&& bytes[1] == b':'
&& matches!(bytes[2], b'/' | b'\\'))
}
/// One `[dotfiles]` whole-file entry as written in mise.toml.View on GitHub (pinned to 533346cc37)