facebook/flow · error · std::io::Error
timed out connecting to named pipe
Error message
timed out connecting to named pipe
What it means
On Windows, SocketStream::connect opens the server's named pipe (\\.\pipe\...) in a retry loop: tokio's ClientOptions::open returns NotFound while the pipe does not exist yet, or ERROR_PIPE_BUSY (231) when all pipe instances are in use, and the loop sleeps 10 ms and retries until a deadline. When the deadline passes you get ErrorKind::TimedOut "timed out connecting to named pipe" — the pipe never became connectable in the window you allowed.
Source
Thrown at rust_port/crates/flow_common_socket/src/socket.rs:313
};
loop {
let result = flow_tokio_runtime::block_on(async {
tokio::net::windows::named_pipe::ClientOptions::new().open(pipe_name)
});
match result {
Ok(client) => {
return Ok(Self {
pipe: Arc::new(NamedPipeStream::Client(client)),
read_timeout: Arc::new(Mutex::new(None)),
write_timeout: Arc::new(Mutex::new(None)),
});
}
Err(e)
if e.kind() == io::ErrorKind::NotFound
|| e.raw_os_error() == Some(ERROR_PIPE_BUSY) =>
{
if std::time::Instant::now() >= deadline {
return Err(io::Error::new(
io::ErrorKind::TimedOut,
"timed out connecting to named pipe",
));
}
std::thread::sleep(Duration::from_millis(10));
}
Err(e) => return Err(e),
}
}
}
}
pub fn try_clone(&self) -> io::Result<Self> {
#[cfg(unix)]
{
Ok(Self {
socket: self.socket.try_clone()?,
})View on GitHub (pinned to f88ac94bcf)
Solutions
- Verify the Flow server is actually running and listening on the exact pipe name the client passes.
- Increase the timeout passed to SocketStream::connect — cold starts (AV scans, debug builds) routinely need seconds, not milliseconds.
- If the server crashed at startup, read its logs/stderr, fix the crash, restart it, then connect.
- Throttle concurrent client connections or retry later when connections report busy.
Example fix
// before: 500ms is too small for a cold server start
let stream = SocketStream::connect(&addr, Duration::from_millis(500))?;
// after: budget for cold start; on TimedOut verify the server and retry once
let stream = match SocketStream::connect(&addr, Duration::from_secs(5)) {
Ok(s) => s,
Err(e) if e.kind() == io::ErrorKind::TimedOut => {
ensure_server_running(&addr)?; // check/restart the server first
SocketStream::connect(&addr, Duration::from_secs(5))?
}
Err(e) => return Err(e),
}; Defensive patterns
Strategy: retry
Type guard
fn is_pipe_connect_timeout(e: &std::io::Error) -> bool {
e.kind() == std::io::ErrorKind::TimedOut && e.to_string().contains("named pipe")
} Try / catch
Branch on ErrorKind::TimedOut: verify/restart the server, then retry the connect once with backoff. Propagate NotFound and other kinds immediately — they indicate a wrong pipe name, not slowness.
Prevention
- Wait for the server's readiness signal (socket/lock file present) before connecting clients.
- Size connect timeouts for cold starts: AV scans and debug builds need seconds.
- Cap concurrent client connections so pipe instances are not all busy.
When it happens
Trigger: Calling SocketStream::connect(&Addr::NamedPipe(..), timeout) against a server that has not created the pipe yet (still initializing or crashed at startup), a server whose pipe instances are all busy, a wrong pipe name, or with a timeout too small for a cold server start.
Common situations: Server binary crashing during startup (check its stderr); antivirus or slow disks delaying process start; many concurrent clients saturating the pipe instances; connecting with a stale pipe name after the server reconfigured.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- socket timeout
- Daemon::spawn: timed out waiting for child to connect
- Daemon::spawn: timed out reading token from child
- Daemon::from_channel: bincode deserialize
- Daemon child: failed to connect to parent out-socket (child
AI-assisted analysis of facebook/flow@f88ac94bcf (2026-08-20).
Data as JSON: /api/errors/914a212ce4cc6ad5.
Report an issue: GitHub.