jdx/mise · error
[dotfiles]." ": mode symlink-each requires a directory…
Error message
[dotfiles]."{}": mode symlink-each requires a directory source: {} What it means
Mode symlink-each creates one symlink per entry inside the source directory, so the source must be a directory. If a [dotfiles] entry uses symlink-each but its source resolves to a regular file (or symlink to a file), the builder rejects it before writing any layer entries.
Solutions
- Point source at the directory containing the individual dotfiles (e.g. /home/me/dotfiles).
- For a single file, change the mode to "symlink" (or "content"/"track") instead of "symlink-each".
- Verify with `ls -la` that the source path is a directory on the build host.
Example fix
// before [dotfiles."~/.vimrc"] mode = "symlink-each" source = "/home/me/.vimrc" // after [dotfiles."~/.vimrc"] mode = "symlink" source = "/home/me/.vimrc"
Defensive patterns
Strategy: validation
Validate before calling
# symlink-each requires a directory source
[ -d "$HOME/dotfiles" ] || { echo "symlink-each source must be a directory" >&2; exit 1; } Prevention
- Use symlink-each only for directories of dotfiles; use symlink/content for single files.
- Don't replace a directory source with a single file without updating the mode.
- Check `ls -la` on source paths when editing [dotfiles] config.
When it happens
Trigger: build (via build_dotfiles_layer) with a [dotfiles] entry like mode = "symlink-each" whose source points at a single file instead of a directory of dotfiles.
Common situations: Copy-pasting a symlink-each config block for a single-file dotfile like .vimrc; the source was a directory when written but was later replaced by a file; confusing symlink-each with the plain symlink mode.
Related errors
- dotfile : encrypt must be a boolean
- [dotfiles]." ": source does not exist
- [dotfiles]." ": source does not exist
- [history] exclude in
- [history] in is not a table
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/91d9ff516d3e7475.
Report an issue: GitHub.
Appendix: source
Thrown at src/oci/builder.rs:1006
"[dotfiles].\"{}\": source does not exist: {}",
req.target_raw,
req.source.display()
);
}
match req.mode {
// a tracked file lives on the machine that tracks it; an image
// has nothing to copy
FileMode::Track => continue,
FileMode::Symlink | FileMode::Copy => {
collect_source_as_files(&req.source, &oci_target_path(req)?, &mut entries)
.wrap_err_with(|| {
format!("adding [dotfiles].\"{}\" to OCI image", req.target_raw)
})?;
}
FileMode::SymlinkEach => {
if !req.source.is_dir() {
bail!(
"[dotfiles].\"{}\": mode symlink-each requires a directory source: {}",
req.target_raw,
req.source.display()
);
}
let target = oci_target_path(req)?;
entries.add_dir(target.clone())?;
for entry in walkdir::WalkDir::new(&req.source).sort_by_file_name() {
let entry = entry?;
let ft = entry.file_type();
if !(ft.is_file() || ft.is_symlink()) {
continue;
}
let rel = entry.path().strip_prefix(&req.source)?;
let path = format!("{target}/{}", rel.to_string_lossy().replace('\\', "/"));
entries.add_file(
path,
file::read(entry.path())?,View on GitHub (pinned to 533346cc37)