{"record":{"id":"c8bca9fd09cde44f","repo":"microsoft/typescript-go","slug":"fswatch-event-overflow-some-changes-were-missed","errorCode":null,"errorMessage":"fswatch: event overflow; some changes were missed","messagePattern":"fswatch: event overflow; some changes were missed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/fswatch/watcher.go","lineNumber":31,"sourceCode":"\n\t\"github.com/microsoft/typescript-go/internal/nativepath\"\n)\n\nvar errNilCallback = errors.New(\"fswatch: callback must not be nil\")\n\n// errRootPath is returned by WatchFile when the supplied path is a\n// filesystem root with no parent directory to watch.\nvar errRootPath = errors.New(\"fswatch: cannot watch a root path\")\n\n// errNotAbsolute is returned by [Watcher.WatchDirectory] and\n// [Watcher.WatchFile] when the supplied path is not absolute.\nvar errNotAbsolute = errors.New(\"fswatch: path must be absolute\")\n\n// ErrOverflow indicates that the kernel event queue overflowed and\n// some filesystem changes were missed. The watch remains\n// active; further events will continue to be delivered. Callers\n// should treat this as a signal to rescan the watched directory.\nvar ErrOverflow = errors.New(\"fswatch: event overflow; some changes were missed\")\n\n// ErrWatchTerminated indicates that the watch was terminated due to\n// an unrecoverable error (e.g. the watched directory was deleted or\n// the watch descriptor was revoked). No further events will be\n// delivered. Call Close to release remaining state.\nvar ErrWatchTerminated = errors.New(\"fswatch: watch terminated\")\n\n// ErrUnavailable indicates that a requested watcher is not\n// available on the current platform.\nvar ErrUnavailable = errors.New(\"fswatch: watcher not available on this platform\")\n\n// ErrFilesystemUnsupported indicates that the active watcher backend cannot\n// operate on the target filesystem, even though the backend is available on\n// the current platform. This happens, for example, with the fanotify backend\n// on filesystems that do not support FID-based watching: name_to_handle_at\n// returning EOPNOTSUPP (some Docker bind mounts backed by virtiofs, gRPC FUSE,\n// or overlayfs) or fanotify_mark returning ENODEV (e.g. NTFS mounted via\n// fuseblk).","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/microsoft/typescript-go/blob/1bcfa18d79a3be41772223d5c05dfe4480e614ff/internal/fswatch/watcher.go#L13-L49","documentation":"Exported sentinel delivered on the WatchCallback when the kernel event queue overflowed and some changes were missed. The watch remains active and later events still arrive; this is a signal to rescan, not a failure to recover from. On Windows it maps to ERROR_NOTIFY_ENUM_DIR (processCompletion sets it via events.setError); on Linux it corresponds to inotify/fanotify queue overflow.","triggerScenarios":"Bulk changes fast enough to exceed the kernel buffer between drains: git checkout, npm install, tar extraction. Callback work slow enough that events accumulate behind it. Windows network shares running the shrunken 64 KB buffer after an ERROR_INVALID_PARAMETER recovery.","commonSituations":"Package managers and build tools touching thousands of files at once. Watching node_modules or build output recursively. Consumers doing heavy processing inside the callback instead of deferring it.","solutions":["On ErrOverflow, rescan the watched directory and rebuild derived state; do not attempt to replay missed events","Keep callback bodies minimal; enqueue work and process it elsewhere so the queue drains fast","For known bulk operations, skip watching during the operation and do one full rescan afterwards"],"exampleFix":"// before\nfunc(events []fswatch.Event, err error) {\n    if err != nil {\n        log.Fatal(err) // wrong: overflow is recoverable\n    }\n    apply(events)\n}\n\n// after\nfunc(events []fswatch.Event, err error) {\n    if errors.Is(err, fswatch.ErrOverflow) {\n        rescan(dir) // rebuild state; watch is still live\n        return\n    }\n    if err != nil {\n        return // terminal errors handled elsewhere\n    }\n    apply(events)\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"func isOverflow(err error) bool {\n    return errors.Is(err, fswatch.ErrOverflow)\n}","tryCatchPattern":"cb := func(events []fswatch.Event, err error) {\n    if errors.Is(err, fswatch.ErrOverflow) {\n        rescanAndRebuild(dir) // watch stays active; missed changes need a rescan\n        return\n    }\n    if err != nil {\n        return // terminal: handled elsewhere\n    }\n    apply(events)\n}","preventionTips":["Treat every callback error path: check ErrOverflow before ErrWatchTerminated","Keep callbacks fast; queue work instead of processing inline","Rescan on overflow instead of trying to reconstruct missed events","Expect overflow during package installs and mass checkouts"],"tags":["overflow","events","kernel","performance","cross-platform"],"backgroundTag":null,"analyzedSha":"1bcfa18d79a3be41772223d5c05dfe4480e614ff","analyzedAt":"2026-08-16T02:12:00.115Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}