astrid-runtime/astrid · error
Windows named-pipe endpoint denied access
Error message
Windows named-pipe endpoint denied access
What it means
ERROR_ACCESS_DENIED from CreateFile is re-mapped to io::ErrorKind::PermissionDenied with this message: the pipe exists, but the caller is not allowed to open it. Since the library scopes pipe names per user SID, this usually indicates the pipe's security descriptor or the per-user naming rejected the caller's identity.
Source
Thrown at crates/astrid-core/src/local_transport/windows.rs:668
Some(ERROR_FILE_NOT_FOUND) => Ok(EndpointState::Absent),
Some(ERROR_PIPE_BUSY | ERROR_SEM_TIMEOUT | ERROR_ACCESS_DENIED) => {
Ok(EndpointState::BusyOrDenied)
},
_ => Err(error),
}
}
fn classify_connect_error(error: io::Error) -> io::Error {
match error.raw_os_error().map(i32::cast_unsigned) {
Some(ERROR_FILE_NOT_FOUND) => io::Error::new(
io::ErrorKind::NotFound,
"Windows named-pipe endpoint is absent",
),
Some(ERROR_PIPE_BUSY) => io::Error::new(
io::ErrorKind::WouldBlock,
"Windows named-pipe endpoint is busy",
),
Some(ERROR_ACCESS_DENIED) => io::Error::new(
io::ErrorKind::PermissionDenied,
"Windows named-pipe endpoint denied access",
),
_ => error,
}
}
struct PipeSecurity {
_descriptor: LocalAllocation,
attributes: SECURITY_ATTRIBUTES,
}
impl PipeSecurity {
fn for_current_user() -> io::Result<Self> {
let user = current_user_sid()?;
let system = well_known_sid(WinLocalSystemSid)?;
let user_sddl = user.to_sddl()?;
let dacl = if user.equals(&system) {View on GitHub (pinned to affd8760f4)
Solutions
- Run the client under the same Windows user account as the server — the pipe name includes the owner's SID, and access is same-user by design.
- Check for sandboxing/integrity-level differences (AppContainer, low integrity) that strip pipe access, and run the client unsandboxed.
- Verify no security software or policy is blocking named-pipe opens; compare `whoami /user` output on both sides.
Defensive patterns
Strategy: validation
Validate before calling
// confirm same-user and non-sandboxed context before connecting // e.g. compare current_user_sid() to the server account; check integrity level
Type guard
fn client_can_open_pipe(current_sid: &Sid, server_sid: &Sid) -> bool {
current_sid.equals(server_sid)
} Try / catch
match transport.connect(&path) {
Err(e) if e.kind() == io::ErrorKind::PermissionDenied
&& e.to_string().contains("denied access") => {
eprintln!("pipe ACL/identity rejected us; check user account and sandboxing");
}
other => other?,
} Prevention
- Run client and server under the same Windows user account.
- Avoid AppContainer/low-integrity sandboxes for the client.
- Check security policies/AV that restrict named-pipe opens in your environment.
When it happens
Trigger: connect() from a process whose token lacks access to the pipe (different user, low-integrity/AppContainer process, restricted token); connecting to a pipe created by another account whose per-user name coincidentally matches; DACL on the pipe instance denies the client.
Common situations: Client running as a service account against a user's pipe; sandboxed (AppContainer/Edge-style) clients; group-policy or AV software restricting named-pipe access.
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 has a null or missing DACL
- named-pipe DACL has {ace_count} entries; expected exactly {e
- named-pipe DACL contains a non-canonical access entry
- named-pipe DACL grants an unexpected or duplicate principal
- named-pipe DACL omits the current user or Local System
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/bc58d47ab34a0587.
Report an issue: GitHub.