wasmerio/wasmer · error · panic
wasi::path_unlink_file for Buffer
Error message
wasi::path_unlink_file for Buffer
What it means
The wasi path_unlink_file syscall does not handle buffer-backed inodes. In path_unlink_file_internal, the match arms handle symlink/file removal via the FS layer, but the catch-all _ arm hits unimplemented! when the target inode (or matched kind) is a Buffer. Unlinking buffer nodes was simply never implemented.
Source
Thrown at lib/wasix/src/syscalls/wasi/path_unlink_file.rs:135
wasi_try_ok!(h.unlink().map_err(fs_error_into_wasi_err));
} else {
// File is closed
// problem with the abstraction, we can't call unlink because there's no handle
// drop mutable borrow on `path`
let path = path.clone();
drop(guard);
wasi_try_ok!(state.fs_remove_file(path));
}
}
Kind::Dir { .. } | Kind::Root { .. } => return Ok(Errno::Isdir),
Kind::Symlink { .. } => {
drop(guard);
let errno = state.fs.remove_symlink_file(host_adjusted_path.as_path());
if errno != Errno::Success {
return Ok(errno);
}
}
_ => unimplemented!("wasi::path_unlink_file for Buffer"),
}
}
}
Ok(Errno::Success)
}
View on GitHub (pinned to 8c4b9ee9d3)
Solutions
- Remove the buffer node through the buffer-management API (drop/replace it in the FS tree) instead of path_unlink_file.
- Pre-check the resolved inode Kind and return Errno::Notsup for buffers instead of calling through.
- Register such blobs as Kind::File if unlink semantics are required.
- Implement the Buffer arm by detaching the buffer from its parent directory.
Example fix
// before
path_unlink_file("/memfs/tmp.bin") // tmp.bin is a Buffer -> panic
// after (guard)
if matches!(&*inode.read(), Kind::Buffer { .. }) {
return Ok(Errno::Notsup);
} Defensive patterns
Strategy: type-guard
Validate before calling
// resolve and check the kind before unlinking
fn unlinkable(state: &FsState, path: &Path) -> bool {
match state.fs.get_inode_at_path(path) {
Ok(inode) => !matches!(&*inode.read(), Kind::Buffer { .. }),
Err(_) => false,
}
} Type guard
fn is_buffer_inode(inode: &Inode) -> bool {
matches!(&*inode.read(), Kind::Buffer { .. })
} Try / catch
let r = std::panic::catch_unwind(AssertUnwindSafe(|| path_unlink_file_internal(state, path, follow)));
if r.is_err() { return Ok(Errno::Notsup); } Prevention
- Do not register cleanup-able temp files as Kind::Buffer nodes
- Delete buffers through their owning driver API, not wasi.path_unlink_file
- Check resolved inode kind before unlink and surface Errno::Notsup
When it happens
Trigger: Guest calls wasi.path_unlink_file on a path that resolves to a Kind::Buffer node in the synthetic FS tree (e.g. an in-memory blob registered as a Buffer), instead of a regular file or symlink.
Common situations: Guests that 'clean up' temp files inside preopened in-memory filesystems where drivers create Buffer nodes; apps ported from other wasi runtimes where buffers are deletable.
Related errors
- state::get_inode_at_path for buffers
- Symlinks in wasi::fd_read
- wasi::platform_clock_time_get(wasi::Clockid::ProcessCputimeI
- wasi::platform_clock_time_get(wasi::Clockid::ThreadCputimeId
- state::get_inode_at_path unknown file type: not file, direct
AI-assisted analysis of wasmerio/wasmer@8c4b9ee9d3 (2026-09-01).
Data as JSON: /api/errors/743f95007aff9367.
Report an issue: GitHub.