tokio-rs/tokio · error · io::Error
unexpected xucred version from LOCAL_PEERCRED
Error message
unexpected xucred version from LOCAL_PEERCRED
What it means
Thrown by tokio's FreeBSD peer-credential retrieval for Unix sockets. After reading LOCAL_PEERCRED into an xucred struct, tokio verifies cr_version equals XUCRED_VERSION; a mismatch means the kernel returned a credential layout tokio cannot interpret safely. It mirrors getpeereid(3) which rejects unknown credential versions.
Source
Thrown at tokio/src/net/unix/ucred.rs:263
&mut len,
);
if ret != 0 {
return Err(io::Error::last_os_error());
}
if len as usize != size_of::<xucred>() {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"unexpected xucred size from LOCAL_PEERCRED",
));
}
let xucred = xucred.assume_init();
// Match `getpeereid(3)` and reject any `xucred` whose version we
// don't know how to interpret.
if xucred.cr_version != XUCRED_VERSION {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"unexpected xucred version from LOCAL_PEERCRED",
));
}
// `cr_pid` is populated by the kernel since FreeBSD 13. PID 0 is
// the kernel scheduler and never a real userland peer, so we
// surface it as `None` rather than a misleading `Some(0)`.
let pid = match xucred.cr_pid__c_anonymous_union.cr_pid {
0 => None,
p => Some(p as unix::pid_t),
};
// `xucred` carries the effective uid in `cr_uid` and the effective
// gid in `cr_groups[0]`, matching what `getpeereid(2)` returns.
Ok(super::UCred {
uid: xucred.cr_uid as unix::uid_t,
gid: xucred.cr_groups[0] as unix::gid_t,View on GitHub (pinned to 625954f365)
Solutions
- Rebuild tokio (and your crate) on the exact FreeBSD version where it runs so XUCRED_VERSION matches the kernel.
- Upgrade tokio to a release that supports the xucred version your kernel emits.
- Avoid peer_cred on the affected host and obtain peer credentials through an out-of-band mechanism (e.g. SO_PEERCRED-equivalent handshake in your protocol).
- If pinned on a mismatched FreeBSD, run inside a jail/kernel of a supported version.
Example fix
// before
let cred = stream.peer_cred()?;
// after (guard against the platform mismatch)
let cred = match stream.peer_cred() {
Ok(c) => c,
Err(e) if e.kind() == io::ErrorKind::InvalidData => {
return Err(Box::new(e));
}
Err(e) => return Err(Box::new(e)),
}; Defensive patterns
Strategy: try-catch
Validate before calling
// No pre-call validation possible; kernel version mismatch surfaces at runtime. // Document the supported FreeBSD version range for your binary.
Try / catch
match stream.peer_cred() {
Ok(cred) => { /* use cred */ },
Err(e) if e.kind() == io::ErrorKind::InvalidData => {
// xucred size or version mismatch on FreeBSD
return Err(e);
}
Err(e) => return Err(e),
} Prevention
- Pin tokio and your build toolchain to a FreeBSD version matching the deployment kernel.
- Document the supported FreeBSD major versions in your release notes.
- Test peer_cred on every FreeBSD version you ship to.
When it happens
Trigger: Calling UCred::from_LOCAL_PEERCRED (via UnixStream::peer_cred / UnixListener peer credential APIs) on FreeBSD where the kernel's xucred version differs from the constant tokio was compiled against.
Common situations: Running a tokio binary built against one FreeBSD major version on a different major version whose xucred ABI changed; running on an older FreeBSD that reports a lower cr_version; cross-version jail or compatibility layers that synthesize credentials.
Related errors
- unexpected xucred size from LOCAL_PEERCRED
- A Tokio 1.x context was found, but it is being shutdown.
- A Tokio 1.x context was found, but it is being shutdown.
- signal driver gone
- task was cancelled
AI-assisted analysis of tokio-rs/tokio@625954f365 (2026-08-11).
Data as JSON: /api/errors/5831fc0702c69535.
Report an issue: GitHub.