astrid-runtime/astrid · error
named-pipe peer process belongs to a different operating-sys
Error message
named-pipe peer process belongs to a different operating-system user
What it means
require_current_user_process_peer compares the peer process's owner SID with the local process's user SID and rejects the connection when they differ. This enforces same-user-only IPC over named pipes, preventing other accounts (or privilege-escalating sessions) from talking to your pipe server.
Source
Thrown at crates/astrid-core/src/local_transport/windows.rs:461
let mut token = ptr::null_mut();
let opened = unsafe { OpenProcessToken(process.0, TOKEN_QUERY, &raw mut token) };
if opened == 0 || token.is_null() {
return Err(last_error("failed to open named-pipe peer process token"));
}
let user_sid = token_user_sid(&OwnedHandle(token))?;
Ok(VerifiedPeerProcess {
process_id,
user_sid,
_process: process,
})
}
fn require_current_user_process_peer(stream: &LocalStream) -> io::Result<VerifiedPeerProcess> {
let peer = peer_process_identity(stream)?;
if peer.user_sid.equals(¤t_user_sid()?) {
Ok(peer)
} else {
Err(io::Error::new(
io::ErrorKind::PermissionDenied,
"named-pipe peer process belongs to a different operating-system user",
))
}
}
fn require_current_user_effective_client(stream: &LocalStream) -> io::Result<()> {
let client_sid = effective_client_user_sid(stream)?;
if client_sid.equals(¤t_user_sid()?) {
Ok(())
} else {
Err(io::Error::new(
io::ErrorKind::PermissionDenied,
"named-pipe client's effective token belongs to a different operating-system user",
))
}
}
View on GitHub (pinned to affd8760f4)
Solutions
- Run the client and server under the same Windows user account.
- Avoid mixing elevation states — run both sides elevated or both non-elevated.
- If cross-user IPC is genuinely required, use a transport designed for it (e.g. TCP on localhost with explicit auth) instead of this same-user pipe.
Example fix
// before (client launched as another user)
Process.Start(new ProcessStartInfo { UserName = "svc", ... });
// after
// launch client as the same interactive user as the pipe server
Process.Start(new ProcessStartInfo { UseShellExecute = true, FileName = "client.exe" }); Defensive patterns
Strategy: validation
Validate before calling
// before connecting, compare SIDs on both sides via whoami /user // or in Rust: assert current_user_sid() equals the account the client runs under
Type guard
fn same_user(peer_sid: &Sid, current: &Sid) -> bool { peer_sid.equals(current) } Try / catch
match listener.accept() {
Err(e) if e.kind() == io::ErrorKind::PermissionDenied
&& e.to_string().contains("different operating-system user") => {
eprintln!("peer ran as another user; reject and keep listening");
}
other => other?,
} Prevention
- Run client and server under the same Windows account.
- Match elevation levels on both sides (both elevated or neither).
- Document the same-user requirement in deployment/service config.
When it happens
Trigger: Calling connect or accept where the client process runs as a different OS user (different account, service account vs. interactive user, elevated vs. standard session mapping to different SIDs).
Common situations: A Windows service (LocalSystem) hosting the pipe while a desktop user app connects; running the client under 'Run as administrator' with a split-token admin SID; connecting across user sessions (RDP vs. console).
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- named-pipe peer process changed during authentication
- named-pipe client's effective token belongs to a different o
- named-pipe client disconnected before transport authenticati
- named-pipe peer PID did not identify the opened process
- named-pipe endpoint path must not contain a parent component
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/44171684697ddcc1.
Report an issue: GitHub.