jdx/mise · error
refusing to remove non-directory path: {}
Error message
refusing to remove non-directory path: {} What it means
For a managed directory with state = "absent", remove_directory() refuses when the path exists but is not a directory (e.g. a regular file or symlink). The declared resource type and the on-disk type disagree, so removal is rejected; recursive only distinguishes remove_dir_all vs remove_dir for real directories.
Source
Thrown at src/system/managed_files.rs:1434
Err(error) => return Err(error.into()),
Ok(metadata) if metadata.file_type().is_dir() => {}
Ok(_) if !replace => {
bail!("refusing to replace non-directory path: {}", path.display())
}
Ok(_) => {
fs::remove_file(path)?;
fs::create_dir(path)?;
}
}
set_metadata(path, owner, group, mode)
}
fn remove_directory(path: &Path, recursive: bool) -> Result<()> {
match fs::symlink_metadata(path) {
Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(()),
Err(err) => Err(err.into()),
Ok(metadata) if !metadata.file_type().is_dir() => {
bail!("refusing to remove non-directory path: {}", path.display())
}
Ok(_) if recursive => fs::remove_dir_all(path).map_err(Into::into),
Ok(_) => fs::remove_dir(path).map_err(Into::into),
}
}
#[cfg(test)]
mod tests {
use super::*;
fn file(path: &str, state: ManagedState) -> ManagedFileRequest {
ManagedFileRequest {
path: PathBuf::from(path),
content: (state == ManagedState::Present).then(|| "content".to_string()),
owner: None,
group: None,
mode: 0o644,
state,View on GitHub (pinned to 9dcfcaa0dc)
Solutions
- Declare it under [bootstrap.files] with state = "absent" instead, matching the actual type
- Or remove the file manually and re-run
Example fix
# before: /opt/app/cache is actually a regular file
[bootstrap.directories]
"/opt/app/cache" = { state = "absent" }
# after
[bootstrap.files]
"/opt/app/cache" = { state = "absent" } Defensive patterns
Strategy: validation
Validate before calling
if state == ManagedState::Absent {
if let Ok(m) = std::fs::symlink_metadata(path) {
if !m.file_type().is_dir() {
return Err(eyre::eyre!("path is not a directory; declare it under [bootstrap.files]"));
}
}
} Type guard
fn directory_removal_is_safe(path: &std::path::Path) -> bool {
match std::fs::symlink_metadata(path) {
Err(_) => true,
Ok(m) => m.file_type().is_dir(),
}
} Prevention
- Verify on-disk types before writing absent declarations
- Keep a single source of truth for which paths are files vs directories
When it happens
Trigger: A [bootstrap.directories] entry with state = "absent" whose path is actually a regular file or symlink on disk.
Common situations: A path repurposed from directory to file between config revisions; stale directory-removal declarations.
Related errors
- refusing to remove directory as a file: {}
- refusing to replace non-directory path: {}
- managed file parent is not a directory: {}
- managed file parent does not exist: {}
- refusing to replace non-file path: {}
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/fefaea9852898401.
Report an issue: GitHub.