wasmerio/wasmer · error
journal restore error: failed to remove directory - {err}
Error message
journal restore error: failed to remove directory - {err} What it means
apply_path_remove_directory replays a PathRemoveDirectory entry by calling path_remove_directory_internal; any error propagates into this bail. The directory removal recorded in the journal could not be reproduced, so the restored filesystem state would diverge from the snapshot and restore stops.
Source
Thrown at lib/wasix/src/journal/effector/syscalls/path_remove_directory.rs:41
pub fn apply_path_remove_directory(
ctx: &mut FunctionEnvMut<'_, WasiEnv>,
fd: Fd,
path: &str,
) -> anyhow::Result<()> {
// see `VIRTUAL_ROOT_FD` for details as to why this exists
if fd == VIRTUAL_ROOT_FD {
ctx.data().state.fs.root_fs.remove_dir(Path::new(path))?;
} else {
let base_dir = ctx.data().state.fs.get_fd(fd).map_err(|err| {
anyhow::format_err!(
"journal restore error: invalid directory descriptor (fd={fd}) - {err}"
)
})?;
if let Err(err) =
crate::syscalls::path_remove_directory_internal(ctx, fd, base_dir, path)
{
bail!("journal restore error: failed to remove directory - {err}");
}
}
Ok(())
}
}
View on GitHub (pinned to 8c4b9ee9d3)
Solutions
- Make the restore environment's filesystem state match the snapshot state at capture time (recreate expected contents).
- Grant write/remove rights to the relevant preopen directory.
- Ensure journals replay in order so prior entries (files created inside the dir) are applied first.
- Retake the snapshot from an environment consistent with the restore target.
Defensive patterns
Strategy: validation
Validate before calling
// Pre-check that the recorded removals are still reproducible
for op in journal.remove_directory_entries() {
let p = env.resolve_preopen_path(op.fd, &op.path)
.ok_or_else(|| anyhow::anyhow!("invalid dir fd {} for restore", op.fd))?;
// dir must exist and be removable at replay time
if !std::path::Path::new(&p).is_dir() {
return Err(anyhow::anyhow!("directory '{}' missing; replay state diverged", p));
}
} Type guard
fn is_removable_dir(p: &std::path::Path) -> bool {
std::fs::read_dir(p).map(|mut d| d.next().is_none()).unwrap_or(false)
} Try / catch
match restore_from_journal(&env, &journal) {
Err(e) if e.to_string().contains("failed to remove directory") => {
eprintln!("dir removal replay failed: {e}; check journal order and fs state");
resume_with_fresh_snapshot()?;
}
other => other?,
} Prevention
- Replay journals in order so prior creations inside the directory are applied first.
- Grant write/remove rights on the target preopen mount.
- Start restore from a filesystem state matching the snapshot's.
When it happens
Trigger: Journal restore replaying PathRemoveDirectory when the target directory doesn't exist (Noent), is not empty (Notempty), the fd is invalid, or the filesystem lacks permission for removal.
Common situations: Restoring into a fresh/already-cleaned filesystem where the directory is already gone; a directory recreated or populated by other restore steps (Notempty); read-only or capability-restricted mounts.
Related errors
- journal restore error: failed to open descriptor (fd={fd}, p
- journal restore error: failed to rename path (old_fd={old_fd
- journal restore error: failed to remove file (fd={fd}, path=
- journal restore error: failed to set clock time (clock_id={c
- journal restore error: failed renumber file descriptor after
AI-assisted analysis of wasmerio/wasmer@8c4b9ee9d3 (2026-09-01).
Data as JSON: /api/errors/3f6f17795623a05b.
Report an issue: GitHub.