{"record":{"id":"901eaa8aada37be8","repo":"tokio-rs/tokio","slug":"unexpected-xucred-size-from-local-peercred","errorCode":null,"errorMessage":"unexpected xucred size from LOCAL_PEERCRED","messagePattern":"unexpected xucred size from LOCAL_PEERCRED","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"tokio/src/net/unix/ucred.rs","lineNumber":252,"sourceCode":"        unsafe {\n            let raw_fd = sock.as_raw_fd();\n\n            let mut xucred = MaybeUninit::<xucred>::zeroed();\n            let mut len = size_of::<xucred>() as socklen_t;\n\n            let ret = getsockopt(\n                raw_fd,\n                SOL_LOCAL,\n                LOCAL_PEERCRED,\n                xucred.as_mut_ptr() as *mut c_void,\n                &mut len,\n            );\n\n            if ret != 0 {\n                return Err(io::Error::last_os_error());\n            }\n            if len as usize != size_of::<xucred>() {\n                return Err(io::Error::new(\n                    io::ErrorKind::InvalidData,\n                    \"unexpected xucred size from LOCAL_PEERCRED\",\n                ));\n            }\n\n            let xucred = xucred.assume_init();\n\n            // Match `getpeereid(3)` and reject any `xucred` whose version we\n            // don't know how to interpret.\n            if xucred.cr_version != XUCRED_VERSION {\n                return Err(io::Error::new(\n                    io::ErrorKind::InvalidData,\n                    \"unexpected xucred version from LOCAL_PEERCRED\",\n                ));\n            }\n\n            // `cr_pid` is populated by the kernel since FreeBSD 13. PID 0 is\n            // the kernel scheduler and never a real userland peer, so we","sourceCodeStart":234,"sourceCodeEnd":270,"githubUrl":"https://github.com/tokio-rs/tokio/blob/625954f365727668cb02d04172b34f1149637728/tokio/src/net/unix/ucred.rs#L234-L270","documentation":"On Apple platforms, getsockopt(LOCAL_PEERCRED) writes an xucred struct; tokio asserts that the returned len equals size_of::<xucred>(). If the kernel wrote a different number of bytes (struct layout/size changed across OS versions), tokio returns InvalidData 'unexpected xucred size from LOCAL_PEERCRED'. A subsequent check also rejects unknown cr_version. It is a defensive guard against ABI drift in the BSD xucred structure.","triggerScenarios":"Calling UCred-related peer credential lookup (getsockopt LOCAL_PEERCRED) on macOS/FreeBSD where the kernel reports an xucred whose byte size differs from what tokio was compiled to expect. Most likely after a major OS upgrade that changed struct xucred.","commonSituations":"Major macOS/BSD upgrade that resized xucred (added/removed fields); running a tokio binary built against one SDK on a newer kernel; embedded/non-standard BSD derivative; cross-compilation toolchain ABI mismatch.","solutions":["Rebuild tokio (and its socket2/libc deps) against the SDK matching the running kernel so size_of::<xucred>() matches.","Upgrade tokio to a release that supports the current OS xucred layout, or downgrade the OS to a compatible version.","Treat the error as non-fatal: fall back to getpeereid(3) or skip peer-credential checks on this platform.","File an upstream issue if the size mismatch appears on a stable OS release — it may be a tokio/libc binding bug."],"exampleFix":"// before\nlet cred = peer_cred.get(&stream).await?; // InvalidData on new macOS\n\n// after\nlet cred = match peer_cred.get(&stream).await {\n    Ok(c) => Some(c),\n    Err(e) if e.kind() == io::ErrorKind::InvalidData => {\n        tracing::warn!(\"LOCAL_PEERCRED size mismatch: {e}; skipping peer creds\");\n        None\n    }\n    Err(e) => return Err(e.into()),\n};","handlingStrategy":"fallback","validationCode":"// No portable pre-check; the size mismatch is an OS/ABI condition.\n// Gate peer-cred calls behind a platform/version probe if you know the range:\n#[cfg(all(unix, any(target_os = \"macos\", target_os = \"freebsd\")))]\nfn try_peer_cred(stream: &UnixStream) -> Option<UCred> {\n    peer_cred.get(stream).await.ok()\n}","typeGuard":"fn is_xucred_size_mismatch(e: &io::Error) -> bool {\n    e.kind() == io::ErrorKind::InvalidData\n        && e.to_string().contains(\"xucred size\")\n}","tryCatchPattern":"match peer_cred.get(&stream).await {\n    Ok(c) => Ok(c),\n    Err(e) if e.to_string().contains(\"xucred size\") => {\n        tracing::warn!(\"LOCAL_PEERCRED ABI mismatch; skipping peer creds: {e}\");\n        Ok(fallback_cred())\n    }\n    Err(e) => Err(e.into()),\n}","preventionTips":["Rebuild tokio and its deps against the SDK matching the running kernel after OS upgrades.","Pin tokio to a release known to support the target macOS/BSD version, or vice versa.","Treat peer-cred lookup as best-effort on BSD-derived platforms; don't hard-fail auth on it.","Report persistent mismatches upstream — they may indicate a binding bug."],"tags":["unix","ucred","macos","bsd","abi","tokio"],"backgroundTag":null,"analyzedSha":"625954f365727668cb02d04172b34f1149637728","analyzedAt":"2026-08-11T17:46:45.378Z","contentChangedAt":"2026-08-11T17:46:45.378Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}