{"record":{"id":"5d6f1f885083ed79","repo":"microsoft/typescript-go","slug":"syncrpcchannel-timed-out-connecting-to-named-pipe","errorCode":null,"errorMessage":"SyncRpcChannel: timed out connecting to named pipe","messagePattern":"SyncRpcChannel: timed out connecting to named pipe","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"_packages/native-preview/src/api/syncChannel.ts","lineNumber":173,"sourceCode":"            // Retry openSync until the child creates the named pipe.\r\n            let fd: number | undefined;\r\n            for (let i = 0; i < 500; i++) {\r\n                try {\r\n                    fd = openSync(pipePath, \"r+\");\r\n                    break;\r\n                }\r\n                catch {\r\n                    if (this.child.exitCode !== null) {\r\n                        throw new Error(\r\n                            `Child process exited with code ${this.child.exitCode} before pipe was ready`,\r\n                        );\r\n                    }\r\n                    Atomics.wait(sleepBuf, 0, 0, 10);\r\n                }\r\n            }\r\n            if (fd === undefined) {\r\n                this.child.kill();\r\n                throw new Error(\"SyncRpcChannel: timed out connecting to named pipe\");\r\n            }\r\n            this.readFd = fd;\r\n            this.writeFd = fd;\r\n            this.pipeFd = fd;\r\n        }\r\n        else {\r\n            // POSIX: use stdio pipe file descriptors directly.\r\n            this.child = spawn(exe, args, {\r\n                stdio: [\"pipe\", \"pipe\", \"inherit\"],\r\n            });\r\n\r\n            const stdout = this.child.stdout! as StdoutWithHandle;\r\n            const stdin = this.child.stdin! as StdinWithHandle;\r\n\r\n            this.readFd = stdout._handle.fd;\r\n            this.writeFd = stdin._handle.fd;\r\n\r\n            if (typeof this.readFd !== \"number\" || this.readFd < 0 || typeof this.writeFd !== \"number\" || this.writeFd < 0) {\r","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/microsoft/typescript-go/blob/1bcfa18d79a3be41772223d5c05dfe4480e614ff/_packages/native-preview/src/api/syncChannel.ts#L155-L191","documentation":"After 500 openSync retries (about 5 seconds) on Windows, if the named pipe still does not exist and the child has not exited, the channel kills the child and throws this timeout. It means the server started but never (or not yet) created its pipe: an extremely slow start, a blocked startup, or pipe creation being prevented by external software.","triggerScenarios":"Thrown at _packages/native-preview/src/api/syncChannel.ts:173 when the library encounters an invalid state.","commonSituations":"Corporate antivirus quarantining or delaying the spawned binary; CI runners with severe CPU contention; first-run signature scans delaying the child for seconds.","solutions":["Retry the Client construction once — transient startup slowness often passes on a warm cache","Exclude the tsgo binary from antivirus/EDR scanning, or run where named pipes are permitted","Verify the child can create pipes at all on the machine (e.g. run the binary manually and look for the pipe)"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { api = new API({ cwd }); } catch (e) { if ((e as Error).message.includes(\"timed out connecting\")) { api = new API({ cwd }); /* one warm retry */ } else throw e; }","preventionTips":["Warm the machine/binary before latency-sensitive startup (first run is slowest)","Exclude the tsgo binary from antivirus scanning on Windows","Retry once on this specific timeout; persistent failures indicate a blocked pipe environment"],"tags":["typescript","spawn","windows","named-pipe","timeout"],"backgroundTag":null,"analyzedSha":"1bcfa18d79a3be41772223d5c05dfe4480e614ff","analyzedAt":"2026-08-16T02:12:00.115Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}