astrid-runtime/astrid · error
Windows named-pipe endpoint is occupied but unavailable
Error message
Windows named-pipe endpoint is occupied but unavailable
What it means
probe() reports EndpointState::BusyOrDenied as io::ErrorKind::WouldBlock with this message: the named pipe exists, but it is occupied (all instances busy, ERROR_PIPE_BUSY) or access is denied, so a connection attempt cannot proceed right now. Unlike the Absent case, retrying later may succeed once the server frees a pipe instance.
Source
Thrown at crates/astrid-core/src/local_transport/windows.rs:338
}
pub(super) fn split(
stream: LocalStream,
) -> (
tokio::io::ReadHalf<LocalStream>,
tokio::io::WriteHalf<LocalStream>,
) {
tokio::io::split(stream)
}
pub(super) fn probe(path: &Path) -> io::Result<()> {
match endpoint_state(path)? {
EndpointState::Available => Ok(()),
EndpointState::Absent => Err(io::Error::new(
io::ErrorKind::NotFound,
"Windows named-pipe endpoint is absent",
)),
EndpointState::BusyOrDenied => Err(io::Error::new(
io::ErrorKind::WouldBlock,
"Windows named-pipe endpoint is occupied but unavailable",
)),
}
}
pub(super) fn endpoint_is_present(path: &Path) -> io::Result<bool> {
Ok(!matches!(endpoint_state(path)?, EndpointState::Absent))
}
pub(super) fn remove_endpoint(path: &Path) -> io::Result<()> {
if endpoint_is_present(path)? {
return Err(io::Error::new(
io::ErrorKind::PermissionDenied,
"Windows named-pipe endpoints are kernel-owned and cannot be removed while live",
));
}
Ok(())View on GitHub (pinned to affd8760f4)
Solutions
- Retry with backoff, or use the client's open_with_retry path which waits for pipe availability on ERROR_PIPE_BUSY
- Increase the server's named-pipe instance count when creating the pipe (nMaxInstances) so concurrent clients can connect
- If it is denial rather than busy, align the client's account with the pipe ACL (see PermissionDenied handling)
Example fix
// before
probe(&pipe_path)?; // WouldBlock when busy
// after
loop {
match probe(&pipe_path) {
Ok(()) => break,
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
tokio::time::sleep(Duration::from_millis(50)).await;
},
Err(e) => return Err(e),
}
} Defensive patterns
Strategy: retry
Try / catch
match probe(&pipe) {
Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => {
// busy or denied: back off and retry, or use open_with_retry
},
other => other?,
} Prevention
- Raise the server's named-pipe instance count to match expected concurrency
- Prefer the built-in open_with_retry path, which waits out ERROR_PIPE_BUSY
- Watch for long-lived connections exhausting instances; pool or recycle client connections
When it happens
Trigger: Calling probe(path) when the pipe's instance count is exhausted (all instances connected) or the pipe ACL denies the probing client (ERROR_ACCESS_DENIED), i.e. endpoint_state returns BusyOrDenied.
Common situations: More clients than the server's pipe instance limit (default CreateNamedPipe instance count of 1) are trying to connect concurrently; long-lived connections exhaust the server's instances; ACL mismatch between client and server accounts.
Understand the failure class
Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.
Related errors
- Windows named-pipe endpoint disappeared while waiting
- Windows named-pipe endpoint is absent
- Windows named-pipe endpoint denied access while waiting
- named-pipe client disconnected before transport authenticati
- 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/9c34a43e4782c6a2.
Report an issue: GitHub.