wasmerio/wasmer · error · panic
Symlinks in wasi::fd_read
Error message
Symlinks in wasi::fd_read
What it means
In wasi::fd_read (used internally by sock_send_file_internal / apply_sock_send_file), reading from an inode whose kind is Symlink hits an explicit `unimplemented!` panic. The WASEX syscall layer simply has no implementation for dereferencing symlinks when reading file contents to send over a socket, so any attempt to do so aborts the process with this panic message.
Source
Thrown at lib/wasix/src/syscalls/wasix/sock_send_file.rs:198
let mut buf = vec![0u8; sub_count as usize];
let amt = virtual_fs::AsyncReadExt::read(pipe, &mut buf[..])
.await
.map_err(map_io_err)?;
buf.truncate(amt);
Ok(buf)
})?);
env = ctx.data();
data
}
Kind::PipeTx { .. }
| Kind::Epoll { .. }
| Kind::EventNotifications { .. } => {
return Ok(Err(Errno::Inval));
}
Kind::Dir { .. } | Kind::Root { .. } => {
return Ok(Err(Errno::Isdir));
}
Kind::Symlink { .. } => unimplemented!("Symlinks in wasi::fd_read"),
Kind::Buffer { buffer } => {
// TODO: optimize with MaybeUninit
let mut buf = vec![0u8; sub_count as usize];
let mut buf_read = &buffer[offset..];
let amt = wasi_try_ok_ok!(
std::io::Read::read(&mut buf_read, &mut buf[..])
.map_err(map_io_err)
);
buf.truncate(amt);
buf
}
}
};
fd_entry
.inner
.offsetView on GitHub (pinned to 8c4b9ee9d3)
Solutions
- Replace the symlink with a real file, or point the guest at the symlink's resolved target instead.
- Resolve the symlink on the host before mapping it into the sandbox (e.g. use a physical path).
- If you control the runtime, implement symlink resolution (readlink + inode follow) in Kind::Symlink handling in sock_send_file.rs and return the target inode's buffer.
- As a workaround, copy the file to a non-symlinked location and read/send from there.
Example fix
// before
Kind::Symlink { .. } => unimplemented!("Symlinks in wasi::fd_read"),
// after (runtime-side fix idea)
Kind::Symlink { resolved, .. } => {
// follow to the resolved inode instead of panicking
self.read_inode(resolved, offset, buf)
} Defensive patterns
Strategy: validation
Validate before calling
// before sending a file over the socket, ensure the path is not a symlink
let md = std::fs::symlink_metadata(path)?;
if md.file_type().is_symlink() {
return Err(io::Error::new(io::ErrorKind::Unsupported, "symlinked files not supported for sock_send_file"));
} Type guard
fn is_regular_file(p: &Path) -> bool {
std::fs::symlink_metadata(p).map(|m| m.is_file()).unwrap_or(false)
} Prevention
- Do not place symlinks inside directories mapped into the WASIX sandbox
- Resolve symlinks on the host (canonicalize) before mounting/packaging files
- Treat this as a process abort (panic), not a catchable WASI errno — pre-validate paths
When it happens
Trigger: Calling the sock_send_file / fd_read syscall path when the source handle's inode is of Kind::Symlink. This is a hard panic (process abort), not a returned Errno.
Common situations: Running a WASIX program that sends a file over a socket where the path in the preopened directory tree is a symlink (e.g. a symlinked log file or symlinked config inside a mapped directory). More common on host setups that use symlinks by default (macOS, Linux dotfiles).
Related errors
- wasi::platform_clock_time_get(wasi::Clockid::ProcessCputimeI
- wasi::platform_clock_time_get(wasi::Clockid::ThreadCputimeId
- wasi::path_unlink_file for Buffer
- wasmer_env_set_memory() is not supported
- Internal error: failed to resolve exported function {}: {e:?
AI-assisted analysis of wasmerio/wasmer@8c4b9ee9d3 (2026-09-01).
Data as JSON: /api/errors/2f87344b2bb6730f.
Report an issue: GitHub.