microsoft/typescript-go · error

failed to create API transport

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.

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.

Appendix: 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)