microsoft/typescript-go · warning

failed to register file watcher: %w

Error message

failed to register file watcher: %w

What it means

WatchFiles (server.go:247-254) failed at the first branch: the server is running its builtin in-process file watcher (used when the client lacks dynamic registration support but the platform — Windows or FSEvents — supports efficient recursive watching) and the watcher backend rejected the registration of the given watcher id and FileSystemWatcher patterns. The error wraps the underlying watcher error with %w.

Source

Thrown at internal/lsp/server.go:250

	projectProgress *projectLoadingProgress

	startWatchdog func(parentPID int)

	flakeLogging lsproto.DiagnosticFlakeLogLevel
}

func (s *Server) Session() *project.Session { return s.session }

// InitComplete returns a channel that is closed when the server has finished
// processing the initialized notification, including the initial configuration
// exchange with the client.
func (s *Server) InitComplete() <-chan struct{} { return s.initComplete }

// WatchFiles implements project.Client.
func (s *Server) WatchFiles(ctx context.Context, id project.WatcherID, watchers []*lsproto.FileSystemWatcher) error {
	if s.builtinWatcher != nil {
		if err := s.builtinWatcher.WatchFiles(string(id), watchers); err != nil {
			return fmt.Errorf("failed to register file watcher: %w", err)
		}
		s.watchers.Add(id)
		return nil
	}
	_, err := sendClientRequest(ctx, s, lsproto.ClientRegisterCapabilityInfo, &lsproto.RegistrationParams{
		Registrations: []*lsproto.Registration{
			{
				Id: string(id),
				RegisterOptions: &lsproto.RegisterOptions{
					WorkspaceDidChangeWatchedFiles: &lsproto.DidChangeWatchedFilesRegistrationOptions{
						Watchers: watchers,
					},
				},
			},
		},
	})
	if err != nil {
		return fmt.Errorf("failed to register file watcher: %w", err)

View on GitHub (pinned to 1bcfa18d79)

Solutions

  1. Read the wrapped cause — it is the watcher backend's error (pattern parse failure, limit, permissions) and dictates the fix.
  2. Raise the OS watch budget (e.g. fs.inotify.max_user_watches / max_user_instances on Linux) or reduce the number/width of watched globs.
  3. Validate watcher glob patterns (glob syntax supported by the backend) before passing them in FileSystemWatcher entries.
  4. If watching is not needed, disable watchEnabled/watcher setup so WatchFiles is not called.

Example fix

// before: overly broad watchers
watchers := []*lsproto.FileSystemWatcher{{ GlobPattern: new("**/*") }}
// after: scope to source files
watchers := []*lsproto.FileSystemWatcher{{ GlobPattern: new("**/*.{ts,tsx,js,jsx}") }}
Defensive patterns

Strategy: try-catch

Validate before calling

// before registering, sanity-check glob patterns
for _, w := range watchers {
    if w.GlobPattern == nil || *w.GlobPattern == "" {
        return fmt.Errorf("watcher glob required")
    }
    if _, err := path.Match(*w.GlobPattern, "x.ts"); err != nil {
        return fmt.Errorf("bad glob %q: %w", *w.GlobPattern, err)
    }
}

Type guard

func watcherGlobsValid(watchers []*lsproto.FileSystemWatcher) bool {
    for _, w := range watchers {
        if w.GlobPattern == nil || *w.GlobPattern == "" {
            return false
        }
    }
    return true
}

Try / catch

if err := client.WatchFiles(ctx, id, watchers); err != nil {
    if strings.Contains(err.Error(), "failed to register file watcher") {
        // log and degrade: continue without watching; edits rely on didChange events
        log.Printf("file watching unavailable: %v", err)
    } else {
        return err
    }
}

Prevention

When it happens

Trigger: Server constructed with a builtin lspwatcher.Watcher and the OS-level watch could not be created: invalid glob pattern in a FileSystemWatcher, watch limits exhausted (inotify/fsevents), the watched path does not exist, or the platform backend errored. The call site is project.Client.WatchFiles during project loading when file watching is enabled.

Common situations: Linux hosts hitting inotify watch limits on large monorepos; Windows/FSEvents path edge cases; malformed watcher globs from configuration; running many server instances against the same tree.

Related errors


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