{"record":{"id":"8347d4a1d117f0f6","repo":"microsoft/typescript-go","slug":"failed-to-register-file-watcher-w","errorCode":null,"errorMessage":"failed to register file watcher: %w","messagePattern":"failed to register file watcher: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/lsp/server.go","lineNumber":250,"sourceCode":"\tprojectProgress *projectLoadingProgress\n\n\tstartWatchdog func(parentPID int)\n\n\tflakeLogging lsproto.DiagnosticFlakeLogLevel\n}\n\nfunc (s *Server) Session() *project.Session { return s.session }\n\n// InitComplete returns a channel that is closed when the server has finished\n// processing the initialized notification, including the initial configuration\n// exchange with the client.\nfunc (s *Server) InitComplete() <-chan struct{} { return s.initComplete }\n\n// WatchFiles implements project.Client.\nfunc (s *Server) WatchFiles(ctx context.Context, id project.WatcherID, watchers []*lsproto.FileSystemWatcher) error {\n\tif s.builtinWatcher != nil {\n\t\tif err := s.builtinWatcher.WatchFiles(string(id), watchers); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to register file watcher: %w\", err)\n\t\t}\n\t\ts.watchers.Add(id)\n\t\treturn nil\n\t}\n\t_, err := sendClientRequest(ctx, s, lsproto.ClientRegisterCapabilityInfo, &lsproto.RegistrationParams{\n\t\tRegistrations: []*lsproto.Registration{\n\t\t\t{\n\t\t\t\tId: string(id),\n\t\t\t\tRegisterOptions: &lsproto.RegisterOptions{\n\t\t\t\t\tWorkspaceDidChangeWatchedFiles: &lsproto.DidChangeWatchedFilesRegistrationOptions{\n\t\t\t\t\t\tWatchers: watchers,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to register file watcher: %w\", err)","sourceCodeStart":232,"sourceCodeEnd":268,"githubUrl":"https://github.com/microsoft/typescript-go/blob/1bcfa18d79a3be41772223d5c05dfe4480e614ff/internal/lsp/server.go#L232-L268","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Read the wrapped cause — it is the watcher backend's error (pattern parse failure, limit, permissions) and dictates the fix.","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.","Validate watcher glob patterns (glob syntax supported by the backend) before passing them in FileSystemWatcher entries.","If watching is not needed, disable watchEnabled/watcher setup so WatchFiles is not called."],"exampleFix":"// before: overly broad watchers\nwatchers := []*lsproto.FileSystemWatcher{{ GlobPattern: new(\"**/*\") }}\n// after: scope to source files\nwatchers := []*lsproto.FileSystemWatcher{{ GlobPattern: new(\"**/*.{ts,tsx,js,jsx}\") }}","handlingStrategy":"try-catch","validationCode":"// before registering, sanity-check glob patterns\nfor _, w := range watchers {\n    if w.GlobPattern == nil || *w.GlobPattern == \"\" {\n        return fmt.Errorf(\"watcher glob required\")\n    }\n    if _, err := path.Match(*w.GlobPattern, \"x.ts\"); err != nil {\n        return fmt.Errorf(\"bad glob %q: %w\", *w.GlobPattern, err)\n    }\n}","typeGuard":"func watcherGlobsValid(watchers []*lsproto.FileSystemWatcher) bool {\n    for _, w := range watchers {\n        if w.GlobPattern == nil || *w.GlobPattern == \"\" {\n            return false\n        }\n    }\n    return true\n}","tryCatchPattern":"if err := client.WatchFiles(ctx, id, watchers); err != nil {\n    if strings.Contains(err.Error(), \"failed to register file watcher\") {\n        // log and degrade: continue without watching; edits rely on didChange events\n        log.Printf(\"file watching unavailable: %v\", err)\n    } else {\n        return err\n    }\n}","preventionTips":["Raise fs.inotify.max_user_watches / max_user_instances on Linux for large trees.","Prefer narrow globs (source extensions) over '**/*'.","Degrade gracefully: the language server can operate on didChange/didOpen notifications alone."],"tags":["lsp","file-watcher","os","inotify"],"backgroundTag":null,"analyzedSha":"1bcfa18d79a3be41772223d5c05dfe4480e614ff","analyzedAt":"2026-08-16T02:12:00.115Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}