astrid-runtime/astrid · error
Windows named-pipe endpoint denied access while waiting
Error message
Windows named-pipe endpoint denied access while waiting
What it means
During the Windows named-pipe open retry loop, ERROR_ACCESS_DENIED from the pipe state check means the endpoint exists but the client is not permitted to access it (the pipe server's ACL denies this user, or the pipe is in a state that refuses new clients). Astrid maps this to io::ErrorKind::PermissionDenied instead of endlessly retrying.
Source
Thrown at crates/astrid-core/src/local_transport/windows.rs:201
.map_err(|_| io::Error::other("named-pipe wait duration overflow"))?
.max(1);
// `WaitNamedPipeW` is synchronous, so isolate it from the async worker.
// Each call is capped at 50 ms: cancelling the outer future stops all
// retries and leaves at most one short detached blocking wait.
tokio::task::spawn_blocking(move || {
let ready = unsafe { WaitNamedPipeW(encoded.as_ptr(), milliseconds) };
if ready != 0 {
return Ok(());
}
let error = io::Error::last_os_error();
match error.raw_os_error().map(i32::cast_unsigned) {
// A bounded timeout is the backoff between open attempts.
Some(ERROR_SEM_TIMEOUT | ERROR_PIPE_BUSY) => Ok(()),
Some(ERROR_FILE_NOT_FOUND) => Err(io::Error::new(
io::ErrorKind::NotFound,
"Windows named-pipe endpoint disappeared while waiting",
)),
Some(ERROR_ACCESS_DENIED) => Err(io::Error::new(
io::ErrorKind::PermissionDenied,
"Windows named-pipe endpoint denied access while waiting",
)),
_ => Err(error),
}
})
.await
.map_err(|error| io::Error::other(format!("named-pipe wait task failed: {error}")))?
}
pub(super) async fn connect_outcome(path: &Path) -> io::Result<ConnectOutcome> {
match connect(path).await {
Ok(stream) => Ok(ConnectOutcome::Connected(stream)),
Err(error) if error.kind() == io::ErrorKind::NotFound => Ok(ConnectOutcome::Absent),
// Named pipes have no stale filesystem node: their namespace object
// vanishes with the last server handle. Busy and access-denied both
// prove that something owns the name and must never trigger a daemon
// boot or unauthenticated fallback.View on GitHub (pinned to affd8760f4)
Solutions
- Run the client under the same user account (or a group allowed by the pipe ACL) as the named-pipe server
- Fix the server to create the pipe with permissive security attributes (NULL security descriptor or a DACL granting the client account FILE_GENERIC_READ/WRITE)
- Check for name collisions: another process may have created a pipe with the same name; use a unique pipe name
Example fix
// before (server) CreateNamedPipeW(name, ..., NULL /* default, often restrictive context */); // after (server) SECURITY_ATTRIBUTES sa = make_dacl_allowing_clients(); CreateNamedPipeW(name, ..., &sa);
Defensive patterns
Strategy: try-catch
Try / catch
match client.open_with_retry(&pipe).await {
Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied => {
return Err(anyhow!("named pipe access denied: run client as an account allowed by the pipe ACL"));
},
other => other?,
} Prevention
- Create the server pipe with a DACL granting the client accounts read/write access
- Run client and server under the same user or a shared group
- Use unique pipe names to avoid taking over a pipe owned by another process
When it happens
Trigger: open_client_with_retry -> wait_for_pipe_availability receives GetLastError == ERROR_ACCESS_DENIED while probing the named pipe before a successful connect.
Common situations: The pipe server was created with a restrictive SECURITY_ATTRIBUTES denying the current user; the client runs as a different account/service than the server; another process owns the pipe name with exclusive 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
- Windows named-pipe endpoint disappeared while waiting
- named-pipe client disconnected before transport authenticati
- Windows named-pipe endpoint is absent
- Windows named-pipe endpoint is occupied but unavailable
- Windows named-pipe endpoints are kernel-owned and cannot be
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/aa4c2d343f72387c.
Report an issue: GitHub.