{"record":{"id":"8e2e8a616c3c2b44","repo":"astrid-runtime/astrid","slug":"windows-named-pipe-endpoint-is-busy","errorCode":null,"errorMessage":"Windows named-pipe endpoint is busy","messagePattern":"Windows named-pipe endpoint is busy","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/astrid-core/src/local_transport/windows.rs","lineNumber":664,"sourceCode":"    }\n\n    let error = io::Error::last_os_error();\n    match error.raw_os_error().map(i32::cast_unsigned) {\n        Some(ERROR_FILE_NOT_FOUND) => Ok(EndpointState::Absent),\n        Some(ERROR_PIPE_BUSY | ERROR_SEM_TIMEOUT | ERROR_ACCESS_DENIED) => {\n            Ok(EndpointState::BusyOrDenied)\n        },\n        _ => Err(error),\n    }\n}\n\nfn classify_connect_error(error: io::Error) -> io::Error {\n    match error.raw_os_error().map(i32::cast_unsigned) {\n        Some(ERROR_FILE_NOT_FOUND) => io::Error::new(\n            io::ErrorKind::NotFound,\n            \"Windows named-pipe endpoint is absent\",\n        ),\n        Some(ERROR_PIPE_BUSY) => io::Error::new(\n            io::ErrorKind::WouldBlock,\n            \"Windows named-pipe endpoint is busy\",\n        ),\n        Some(ERROR_ACCESS_DENIED) => io::Error::new(\n            io::ErrorKind::PermissionDenied,\n            \"Windows named-pipe endpoint denied access\",\n        ),\n        _ => error,\n    }\n}\n\nstruct PipeSecurity {\n    _descriptor: LocalAllocation,\n    attributes: SECURITY_ATTRIBUTES,\n}\n\nimpl PipeSecurity {\n    fn for_current_user() -> io::Result<Self> {","sourceCodeStart":646,"sourceCodeEnd":682,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-core/src/local_transport/windows.rs#L646-L682","documentation":"ERROR_PIPE_BUSY from CreateFile means the pipe exists but all its instances currently have a waiting client or are occupied — no free instance to serve a new connection. The library maps it to io::ErrorKind::WouldBlock, signaling a transient condition the caller should retry (possibly after the server calls CreateNamedPipe again for a new instance).","triggerScenarios":"Multiple clients connecting concurrently to a single-instance pipe server; server accept loop busy so no instance is listening; client already queued for one instance while opening another.","commonSituations":"High-concurrency IPC where the server created too few pipe instances; slow accept loop under load; thundering-herd client reconnects after a server restart.","solutions":["Retry the connect on WouldBlock with short backoff — this is the intended handling for ERROR_PIPE_BUSY.","Increase server concurrency: accept promptly and recreate pipe instances, or use WaitNamedPipe to wait for a free instance before connecting.","Reduce client concurrency or pool connections to the pipe."],"exampleFix":"// before\nlet stream = transport.connect(&path)?;\n// after\nlet stream = loop {\n    match transport.connect(&path) {\n        Ok(s) => break s,\n        Err(e) if e.kind() == io::ErrorKind::WouldBlock => { std::thread::sleep(BACKOFF); }\n        Err(e) => return Err(e),\n    }\n};","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match transport.connect(&path) {\n    Err(e) if e.kind() == io::ErrorKind::WouldBlock => {\n        // all instances busy: exponential backoff, optionally WaitNamedPipe first\n        std::thread::sleep(BACKOFF);\n        retry_connect(&path)\n    }\n    other => other,\n}","preventionTips":["Keep the server accept loop fast so instances free up quickly.","Create multiple pipe instances for high-concurrency IPC.","Add client-side jittered backoff instead of tight reconnect loops."],"tags":["windows","named-pipes","ipc","busy","retry"],"backgroundTag":"rate-limit-exceeded","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}