wasmerio/wasmer · error

journal restore error: failed renumber file descriptor after

Error message

journal restore error: failed renumber file descriptor after duplicate (from={}, to={}) - {}

What it means

apply_fd_duplicate duplicates a descriptor during journal replay; if the duplicated fd doesn't land on the number recorded in the journal (ret_fd != copied_fd), it renumbers and that fd_renumber_internal call failed. The restored fd table then cannot match the snapshotted layout, so restore aborts.

Source

Thrown at lib/wasix/src/journal/effector/syscalls/fd_duplicate.rs:35

        )
    }

    pub fn apply_fd_duplicate(
        ctx: &mut FunctionEnvMut<'_, WasiEnv>,
        original_fd: Fd,
        copied_fd: Fd,
        cloexec: bool,
    ) -> anyhow::Result<()> {
        let ret_fd = crate::syscalls::fd_dup_internal(ctx, original_fd, 0, cloexec)
            .map_err(|err| {
                anyhow::format_err!(
                    "journal restore error: failed to duplicate file descriptor (original={original_fd}, copied={copied_fd}) - {err}")
            })?;

        if ret_fd != copied_fd {
            let ret = crate::syscalls::fd_renumber_internal(ctx, ret_fd, copied_fd);
            if !matches!(ret, Ok(Errno::Success)) {
                bail!(
                    "journal restore error: failed renumber file descriptor after duplicate (from={}, to={}) - {}",
                    ret_fd,
                    copied_fd,
                    ret.unwrap_or(Errno::Unknown)
                );
            }
        }

        Ok(())
    }
}

View on GitHub (pinned to 8c4b9ee9d3)

Solutions

  1. Take a fresh snapshot and restore from it.
  2. Check for fd number conflicts in the restoring environment.
  3. Use matching wasmer/wasix versions for snapshot creation and restore.
  4. Validate journal integrity (no truncation or out-of-order entries).
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure no restore-time allocations will collide with journal fd numbers
let journal_fds: std::collections::HashSet<u32> = journal.expected_fds().into_iter().collect();
if journal_fds.iter().any(|fd| env.fd_in_use(*fd)) {
    return Err(anyhow::anyhow!("fd table conflicts with journal; restore into a clean env"));
}

Try / catch

match restore_from_journal(&env, &journal) {
    Err(e) if e.to_string().contains("after duplicate") => {
        eprintln!("fd renumber after dup failed: {e}");
        resume_with_fresh_snapshot()?;
    }
    other => other?,
}

Prevention

When it happens

Trigger: Journal restore replaying an FdDuplicate entry when fd_renumber_internal fails to move the fresh duplicate to the expected copied_fd (target fd invalid or occupied).

Common situations: Snapshot fd tables that conflict with fds allocated during restore; corrupted journals; version mismatch between the runtime that produced the journal and the restoring runtime.

Related errors


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