microsoft/typescript-go · error

failed to create API transport: %w

Error message

failed to create API transport: %w

What it means

Returned when the API session setup fails at api.NewPipeTransport, i.e. the OS-level listener could not be created on the pipe path. On Unix this creates a Unix domain socket; on Windows a named pipe. Typical underlying failures: the socket path exceeds the kernel limit (~104-108 bytes for sun_path), a stale socket file already occupies the address, the parent directory does not exist or is not writable, or Windows rejects the pipe name format.

Source

Thrown at internal/lsp/server.go:1868

	if s.apiSessions == nil {
		s.apiSessions = make(map[string]*api.Session)
	}

	var apiSession *api.Session
	apiSession = api.NewSession(s.session, nil)

	// Use provided pipe path or generate a unique one
	var pipePath string
	if params.Pipe != nil && *params.Pipe != "" {
		pipePath = *params.Pipe
	} else {
		pipePath = s.generateAPIPipePath()
	}

	transport, err := api.NewPipeTransport(pipePath)
	if err != nil {
		return nil, fmt.Errorf("failed to create API transport: %w", err)
	}

	// Start accepting connections in the background
	go func() {
		defer func() {
			apiSession.Close()
			s.removeAPISession(apiSession.ID())
		}()

		rwc, acceptErr := transport.Accept()
		_ = transport.Close()
		if acceptErr != nil {
			s.logger.Errorf("API session %s: failed to accept connection: %v", apiSession.ID(), acceptErr)
			return
		}

		// Create a cancellable context for the API connection
		apiCtx, apiCancel := context.WithCancel(s.backgroundCtx)

View on GitHub (pinned to 1bcfa18d79)

Solutions

  1. Pass an explicit, short Pipe path in a directory you know is writable (params.Pipe)
  2. If reusing a fixed path, unlink/remove the stale socket file before starting (Unix)
  3. Verify the parent directory exists and the process has create permissions
  4. On Windows, use a valid \\.\pipe\name form; on Unix keep the absolute path under ~100 chars

Example fix

// before
params := &lsproto.OpenApiSessionParams{} // auto-generated path

// after
p := "/tmp/api-" + pid
os.Remove(p) // clear stale socket
params := &lsproto.OpenApiSessionParams{Pipe: &p}
Defensive patterns

Strategy: validation

Validate before calling

// Unix: keep socket path short and pre-clear stale files
if len(pipePath) > 100 {
	pipePath = filepath.Join("/tmp", fmt.Sprintf("api-%d", os.Getpid()))
}
os.Remove(pipePath) // stale socket from a previous run
if dir := filepath.Dir(pipePath); dir != "." {
	_ = os.MkdirAll(dir, 0o755)
}

Try / catch

transport, err := api.NewPipeTransport(pipePath)
if err != nil {
	// one retry with a fresh short path in temp dir
	pipePath = filepath.Join(os.TempDir(), fmt.Sprintf("api-%d-%d", os.Getpid(), time.Now().UnixNano()))
	transport, err = api.NewPipeTransport(pipePath)
	if err != nil {
		return nil, fmt.Errorf("failed to create API transport: %w", err)
	}
}

Prevention

When it happens

Trigger: Calling the API-session request with no Pipe param so the generated path is long; passing a Pipe path whose parent dir was deleted; leftover socket file from a crashed previous run; running in a sandboxed/container env where the default temp dir forbids socket creation; Windows path missing the \\.\pipe\ prefix form.

Common situations: Long TMPDIR paths in CI containers; multiple server instances colliding on a fixed pipe path; permissions in restricted service accounts; macOS tmp cleanup removing the directory mid-session.

Related errors


AI-assisted analysis of microsoft/typescript-go@1bcfa18d79 (2026-08-16). Data as JSON: /api/errors/1d894912f87debcc. Report an issue: GitHub.