jdx/mise · error
managed file parent does not exist: {}
Error message
managed file parent does not exist: {} What it means
write_file() requires the parent directory to exist - mise does not implicitly mkdir -p for managed files. If fs::metadata(parent) returns NotFound, the write is refused before any mutation happens, leaving the old state intact.
Source
Thrown at src/system/managed_files.rs:1361
fn write_file(
path: &Path,
content: &[u8],
owner: Option<&str>,
group: Option<&str>,
mode: u32,
replace: bool,
) -> Result<()> {
let parent = path
.parent()
.ok_or_else(|| eyre!("managed file has no parent: {}", path.display()))?;
match fs::metadata(parent) {
Ok(metadata) if metadata.is_dir() => {}
Ok(_) => bail!(
"managed file parent is not a directory: {}",
parent.display()
),
Err(error) if error.kind() == std::io::ErrorKind::NotFound => {
bail!("managed file parent does not exist: {}", parent.display())
}
Err(error) => return Err(error.into()),
}
// Prepare the complete replacement before mutating the destination. In
// particular, a metadata permission error must leave the old path intact.
let mut temporary = tempfile::NamedTempFile::new_in(parent)?;
temporary.write_all(content)?;
set_metadata(temporary.path(), owner, group, mode)?;
temporary.as_file_mut().sync_all()?;
match fs::symlink_metadata(path) {
Err(error) if error.kind() == std::io::ErrorKind::NotFound => {}
Err(error) => return Err(error.into()),
Ok(metadata) if metadata.file_type().is_file() => {}
Ok(_) if !replace => {
bail!("refusing to replace non-file path: {}", path.display())
}
Ok(metadata) if metadata.file_type().is_dir() => {
fs::remove_dir(path).wrap_err_with(|| {View on GitHub (pinned to 9dcfcaa0dc)
Solutions
- Add a [bootstrap.directories] entry for the parent so the run creates it before the file
- Or pre-create the directory yourself: sudo mkdir -p /opt/app
Example fix
# before
[bootstrap.files]
"/opt/app/settings.conf" = { content = "..." }
# after
[bootstrap.directories]
"/opt/app" = { owner = "app", mode = "0755" }
[bootstrap.files]
"/opt/app/settings.conf" = { content = "...", mode = "0644" } Defensive patterns
Strategy: validation
Validate before calling
let parent = path.parent().ok_or_else(|| eyre::eyre!("no parent"))?;
if !parent.exists() {
return Err(eyre::eyre!("managed file parent does not exist: {}", parent.display()));
} Type guard
fn parent_exists(path: &std::path::Path) -> bool {
path.parent().map(|p| p.exists()).unwrap_or(false)
} Prevention
- Declare parent directories in [bootstrap.directories] alongside nested files
- On fresh machines, run the full bootstrap rather than partial applies
When it happens
Trigger: Declaring [bootstrap.files] "/opt/app/settings.conf" when /opt/app (or an ancestor) does not exist and no matching [bootstrap.directories] entry creates it.
Common situations: Fresh machine where the application directory was never created; assuming managed files auto-create their parent directories.
Related errors
- task includes do not contain an existing directory where a f
- not a directory: {}
- managed system files are only supported on Unix
- managed system path must be absolute: {}
- mode must be between 0000 and 7777
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/17ba3350627d41f0.
Report an issue: GitHub.