wasmerio/wasmer · error

journal restore error: failed to rename path (old_fd={old_fd

Error message

journal restore error: failed to rename path (old_fd={old_fd}, old_path={old_path}, new_fd={new_fd}, new_path={new_path}) - {ret}

What it means

apply_path_rename replays a PathRename entry; in the non-async/stateless path, path_rename_internal must return Errno::Success, otherwise this bail fires with the old/new fds and paths. The rename from the snapshot could not be reproduced, leaving the restored filesystem inconsistent.

Source

Thrown at lib/wasix/src/journal/effector/syscalls/path_rename.rs:43

        ctx: &mut FunctionEnvMut<'_, WasiEnv>,
        old_fd: Fd,
        old_path: &str,
        new_fd: Fd,
        new_path: &str,
    ) -> anyhow::Result<()> {
        // see `VIRTUAL_ROOT_FD` for details as to why this exists
        if old_fd == VIRTUAL_ROOT_FD && new_fd == VIRTUAL_ROOT_FD {
            let state = ctx.data().state.clone();
            let old_path = old_path.to_string();
            let new_path = new_path.to_string();
            __asyncify_light(ctx.data(), None, async move {
                state.fs_rename(old_path, new_path).await
            })??;
        } else {
            let ret =
                crate::syscalls::path_rename_internal(ctx, old_fd, old_path, new_fd, new_path)?;
            if ret != Errno::Success {
                bail!(
                    "journal restore error: failed to rename path (old_fd={old_fd}, old_path={old_path}, new_fd={new_fd}, new_path={new_path}) - {ret}"
                );
            }
        }
        Ok(())
    }
}

View on GitHub (pinned to 8c4b9ee9d3)

Solutions

  1. Align the filesystem contents of the restore environment with the snapshot (ensure old_path exists and new_path's parent exists).
  2. Grant write rights on both source and destination preopen directories.
  3. Ensure journal entries are applied in the original order.
  4. Use the same runtime version for snapshot creation and restore.
Defensive patterns

Strategy: validation

Validate before calling

// Pre-flight: old_path must exist and new_path's parent must exist
for op in journal.rename_entries() {
    let from = env.resolve_preopen_path(op.old_fd, &op.old_path)
        .ok_or_else(|| anyhow::anyhow!("bad old_fd {} for restore", op.old_fd))?;
    if !std::path::Path::new(&from).exists() {
        return Err(anyhow::anyhow!("rename source '{}' missing at restore", from));
    }
}

Type guard

fn rename_source_ok(p: &std::path::Path) -> bool {
    std::fs::symlink_metadata(p).is_ok()
}

Try / catch

match restore_from_journal(&env, &journal) {
    Err(e) if e.to_string().contains("failed to rename path") => {
        eprintln!("rename replay failed: {e}; syncing fs state and retrying");
        sync_fs_and_retry()?;
    }
    other => other?,
}

Prevention

When it happens

Trigger: Journal restore replaying PathRename when the source path doesn't exist (Noent), source or base fds are invalid, destination directory is missing, or capability rights prevent the rename.

Common situations: Restoring onto a filesystem where the old_path was already renamed or removed; mismatched mounts between capture and restore hosts; missing write rights on the destination directory preopen.

Related errors


AI-assisted analysis of wasmerio/wasmer@8c4b9ee9d3 (2026-09-01). Data as JSON: /api/errors/e66c0a75b63156f5. Report an issue: GitHub.