{"record":{"id":"b0435f00fe909ea1","repo":"microsoft/typescript-go","slug":"no-file-watcher-exists-with-id-s","errorCode":null,"errorMessage":"no file watcher exists with ID %s","messagePattern":"no file watcher exists with ID (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/lsp/server.go","lineNumber":279,"sourceCode":"\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)\n\t}\n\n\ts.watchers.Add(id)\n\treturn nil\n}\n\n// UnwatchFiles implements project.Client.\nfunc (s *Server) UnwatchFiles(ctx context.Context, id project.WatcherID) error {\n\tif s.builtinWatcher != nil {\n\t\tif !s.watchers.Has(id) {\n\t\t\treturn fmt.Errorf(\"no file watcher exists with ID %s\", id)\n\t\t}\n\t\tif err := s.builtinWatcher.UnwatchFiles(string(id)); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to unregister file watcher: %w\", err)\n\t\t}\n\t\ts.watchers.Delete(id)\n\t\treturn nil\n\t}\n\tif s.watchers.Has(id) {\n\t\t_, err := sendClientRequest(ctx, s, lsproto.ClientUnregisterCapabilityInfo, &lsproto.UnregistrationParams{\n\t\t\tUnregisterations: []*lsproto.Unregistration{\n\t\t\t\t{\n\t\t\t\t\tId:     string(id),\n\t\t\t\t\tMethod: string(lsproto.MethodWorkspaceDidChangeWatchedFiles),\n\t\t\t\t},\n\t\t\t},\n\t\t})\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to unregister file watcher: %w\", err)","sourceCodeStart":261,"sourceCodeEnd":297,"githubUrl":"https://github.com/microsoft/typescript-go/blob/1bcfa18d79a3be41772223d5c05dfe4480e614ff/internal/lsp/server.go#L261-L297","documentation":"UnwatchFiles (server.go:276-280) with the builtin watcher active: the requested project.WatcherID is not in the server's registered set (s.watchers), so there is nothing to remove. It is a caller-state error — the id was never registered or was already unwatched, and the error names the offending id.","triggerScenarios":"Calling project.Client.UnwatchFiles with an id that was never passed to WatchFiles, calling UnwatchFiles twice for the same id (the first call deletes it from the set), or a session tracking bug that loses which watcher ids are live.","commonSituations":"Retry logic that re-runs cleanup and hits the second UnwatchFiles; multiple projects sharing one client and double-releasing watchers; tests constructing arbitrary WatcherIDs.","solutions":["Track watcher ids returned/created by your session layer and only unwatch ids you successfully registered (WatchFiles returned nil).","Make cleanup idempotent in the caller: guard with your own 'registered' set or ignore this specific error during teardown.","If hit on first unwatch, audit for a lost WatchFiles error that was swallowed earlier — registration may have failed and the id never entered s.watchers."],"exampleFix":"// before\n_ = client.UnwatchFiles(ctx, id)\n// after: idempotent cleanup\nif registered.Has(id) {\n    if err := client.UnwatchFiles(ctx, id); err != nil { return err }\n    registered.Delete(id)\n}","handlingStrategy":"validation","validationCode":"// caller-side registry of live watcher ids\nvar liveWatchers collections.SyncSet[project.WatcherID]\n\nfunc register(ctx context.Context, c project.Client, id project.WatcherID, ws []*lsproto.FileSystemWatcher) error {\n    if err := c.WatchFiles(ctx, id, ws); err != nil {\n        return err\n    }\n    liveWatchers.Add(id)\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if err := client.UnwatchFiles(ctx, id); err != nil {\n    if strings.HasPrefix(err.Error(), \"no file watcher exists with ID\") {\n        // already gone: benign during idempotent teardown\n        return nil\n    }\n    return err\n}","preventionTips":["Record ids only after WatchFiles succeeds; WatchFiles adds to s.watchers only on success.","Make teardown idempotent with a caller-side registry.","Never synthesize WatcherIDs; use the ones issued at registration time."],"tags":["lsp","file-watcher","state-management"],"backgroundTag":null,"analyzedSha":"1bcfa18d79a3be41772223d5c05dfe4480e614ff","analyzedAt":"2026-08-16T02:12:00.115Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}