jdx/mise · error
[dotfiles]."{}": manifest requires the source to be a direct
Error message
[dotfiles]."{}": manifest requires the source to be a directory: {} What it means
validate_composed_file_footprints enforces that a manifest-backed dotfile declaration owns a directory as its source, since the manifest enumerates the files inside it. A non-Track request that has a manifest but whose source path exists and is not a directory is rejected with this error; Track requests are skipped because they own no apply leaf.
Source
Thrown at src/system/files.rs:416
}
/// Validate the complete paths claimed by composed `[dotfiles]` entries.
/// Directory copies and `symlink-each` entries may share directories, but no
/// two entries may own the same leaf or require a directory where another
/// entry places a leaf.
pub(crate) fn validate_composed_file_footprints(requests: &[FileRequest]) -> Result<()> {
let mut leaves: IndexMap<PathBuf, &FileRequest> = IndexMap::new();
let mut directories: IndexMap<PathBuf, &FileRequest> = IndexMap::new();
let mut symlink_each_identities: HashMap<(&Path, &Path), &FileRequest> = HashMap::new();
for request in requests {
// Tracking observes native files; it does not own an apply leaf.
// A tracked parent may contain independently managed destinations.
if request.mode == FileMode::Track {
continue;
}
if request.manifest.is_some() && request.source.exists() && !request.source.is_dir() {
bail!(
"[dotfiles].\"{}\": manifest requires the source to be a directory: {}",
request.target_raw,
request.source.display_user()
);
}
if request.mode == FileMode::SymlinkEach
&& let Some(existing) = symlink_each_identities.insert(
(request.source.as_path(), request.target.as_path()),
request,
)
{
return Err(composed_file_footprint_conflict(
&request.target,
existing,
request,
));
}
// A missing source has an unknown eventual shape, but it still claimsView on GitHub (pinned to afd2eddd3a)
Solutions
- Point the declaration's source at the directory that contains the files listed in the manifest.
- Remove the manifest key if you intend to manage a single file directly.
- Recreate the directory layout the manifest expects (move the file into the expected directory).
Example fix
# before: manifest with a file source [dotfiles."~/.config"] source = "~/dotfiles/config.toml" manifest = "manifest.toml" # after: source is the directory [dotfiles."~/.config"] source = "~/dotfiles" manifest = "manifest.toml"
Defensive patterns
Strategy: validation
Validate before calling
# manifest sources must be directories p=$(mise get dotfile-source ~/.config); [ -d "$p" ] || echo "not a directory: $p"
Type guard
const manifestSourceIsDir = (p: string) => fs.existsSync(p) && fs.statSync(p).isDirectory();
Prevention
- Point manifest-backed entries at directories, not files
- Omit the manifest key for single-file declarations
- Re-check the source path after restructuring your dotfiles repo
When it happens
Trigger: Calling any of the plan/validate entry points (plan_apply_with_active, the composed_symlink_each_* validators, tracking footprint checks) with a FileRequest where manifest.is_some(), source.exists(), and !source.is_dir() — i.e. a [dotfiles] entry points at a regular file while declaring a manifest.
Common situations: The user points a manifest dotfile at a single file instead of the directory containing it (e.g. source = "~/dotfiles/gitconfig" with a manifest, instead of source = "~/dotfiles"), or the source was replaced by a file after being a directory.
Related errors
- invalid or repeated variant for {}
- invalid or unenrolled permission path {path}
- dotfile enrollment metadata must be a regular file
- cached rustc output set is incomplete
- the packslip names an executable {:?}, which is not a plain
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/1f77386e6909e16e.
Report an issue: GitHub.