microsoft/typescript-go · error
failed to create pipe transport: %w
Error message
failed to create pipe transport: %w
What it means
StdioServer.Run failed to create the pipe transport: NewPipeTransport could not listen on the configured PipePath (a Unix domain socket on Unix, a named pipe on Windows). The underlying net.Listen error is wrapped, so the message includes the OS-level cause (address already in use, permission denied, socket path too long, invalid pipe name). The server cannot start and Run returns before accepting any connection.
Source
Thrown at internal/api/server.go:62
// NewStdioServer creates a new STDIO-based API server.
func NewStdioServer(options *StdioServerOptions) *StdioServer {
if options.Cwd == "" {
panic("StdioServerOptions.Cwd is required")
}
return &StdioServer{
options: options,
}
}
// Run starts the server and blocks until the connection closes.
func (s *StdioServer) Run(ctx context.Context) error {
var transport Transport
if s.options.PipePath != "" {
t, err := NewPipeTransport(s.options.PipePath)
if err != nil {
return fmt.Errorf("failed to create pipe transport: %w", err)
}
defer t.Close()
transport = t
} else {
t := NewStdioTransport(s.options.In, s.options.Out)
defer t.Close()
transport = t
}
fs := bundled.WrapFS(osvfs.FS())
// Wrap the base FS with callbackFS if callbacks are requested
var callbackFS *callbackFS
if len(s.options.Callbacks) > 0 {
callbackFS = newCallbackFS(fs, s.options.Callbacks)
fs = callbackFS
}
View on GitHub (pinned to 1bcfa18d79)
Solutions
- Remove the stale socket file at PipePath before starting (os.Remove(path), ignoring not-exist), then retry Run
- Use a unique PipePath per server instance (e.g. include PID or generate a temp name) to avoid collisions
- Shorten the path so it fits the OS limit, or place sockets in a short directory like /tmp
- Check the wrapped error text for the OS cause: 'address already in use' -> stale socket, 'permission denied' -> directory rights, 'invalid argument' -> bad pipe name/format
Example fix
// before
srv := api.NewStdioServer(&api.StdioServerOptions{Cwd: cwd, PipePath: "/tmp/ts-api.sock"})
err := srv.Run(ctx) // failed to create pipe transport: address already in use
// after
const sock = "/tmp/ts-api.sock"
if _, err := os.Stat(sock); err == nil {
_ = os.Remove(sock) // clear stale socket from a crashed run
}
srv := api.NewStdioServer(&api.StdioServerOptions{Cwd: cwd, PipePath: sock})
err := srv.Run(ctx) Defensive patterns
Strategy: validation
Validate before calling
// Go: clear a stale socket and sanity-check the path before Run.
func preparePipePath(path string) error {
if fi, err := os.Stat(path); err == nil {
if fi.Mode()&os.ModeSocket != 0 {
if err := os.Remove(path); err != nil {
return fmt.Errorf("stale socket %s not removable: %w", path, err)
}
} else {
return fmt.Errorf("%s exists and is not a socket", path)
}
}
if runtime.GOOS != "windows" && len(path) >= 104 {
return fmt.Errorf("socket path too long for AF_UNIX: %s", path)
}
return nil
} Try / catch
err := srv.Run(ctx)
if err != nil && strings.Contains(err.Error(), "failed to create pipe transport") {
cause := errors.Unwrap(err)
if errors.Is(cause, syscall.EADDRINUSE) {
// stale socket: remove and restart once
_ = os.Remove(pipePath)
err = srv.Run(ctx)
}
} Prevention
- Include the PID in the pipe path so concurrent instances never collide
- Clean up the socket file via defer on server shutdown
- Keep socket paths short (/tmp, not nested temp dirs) on Unix
- On Windows, use a unique name under \\.\pipe\
When it happens
Trigger: A stale socket file already exists at PipePath from a previous crashed process (EADDRINUSE); the socket path exceeds the ~108-byte Unix domain socket limit; permission denied on the directory; two server instances configured with the same PipePath; a malformed Windows pipe name that is not under \\.\pipe\.
Common situations: Restarting a tool whose previous process did not clean up its socket; long temp-dir paths (CI runners, macOS $TMPDIR) blowing past the unix socket path limit; running two editor integrations side by side that both hardcode the same pipe path; sandboxed environments denying unix socket creation.
Related errors
- Child process exited with code ${this.child.exitCode} before
- failed to accept connection: %w
- failed to create API transport: %w
- Invalid value for ${name}: ${value}
- Destination directory does not exist: ${dstDir}
AI-assisted analysis of microsoft/typescript-go@1bcfa18d79 (2026-08-16).
Data as JSON: /api/errors/ad2680f707c676a2.
Report an issue: GitHub.