{"record":{"id":"e99280c02eba8172","repo":"microsoft/typescript-go","slug":"fswatch-watcher-backend-unsupported-on-this-files","errorCode":null,"errorMessage":"fswatch: watcher backend unsupported on this filesystem","messagePattern":"fswatch: watcher backend unsupported on this filesystem","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/fswatch/watcher.go","lineNumber":50,"sourceCode":"\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).\nvar ErrFilesystemUnsupported = errors.New(\"fswatch: watcher backend unsupported on this filesystem\")\n\n// Watcher represents a filesystem watching implementation.\n// Use one of the constructor functions ([Inotify], [FSEvents], [Kqueue],\n// [Windows]) to obtain a value, or [Default] for the platform default.\n//\n// All watchers exist on every platform. Subscribing with a watcher that\n// is not supported on the current OS returns [ErrUnavailable].\ntype Watcher interface {\n\t// Name returns a stable identifier (\"inotify\", \"fsevents\", \"kqueue\",\n\t// \"windows\").\n\tName() string\n\t// Available reports whether this watcher works on the current OS.\n\tAvailable() bool\n\t// HasFastRecursiveBackend reports whether this watcher supports efficient\n\t// recursive watching without requiring a full userspace tree walk. This is\n\t// true for Windows (ReadDirectoryChangesW subtree mode) and macOS FSEvents\n\t// (inherently recursive), and false for all other backends.\n\tHasFastRecursiveBackend() bool","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/microsoft/typescript-go/blob/1bcfa18d79a3be41772223d5c05dfe4480e614ff/internal/fswatch/watcher.go#L32-L68","documentation":"Exported sentinel: the backend exists on this platform but cannot watch the target filesystem. The concrete case is fanotify on filesystems without FID support: name_to_handle_at returning EOPNOTSUPP (Docker bind mounts backed by virtiofs, gRPC FUSE, overlayfs) or fanotify_mark returning ENODEV (NTFS via fuseblk); fanotify_linux.go wraps those errnos with this sentinel. Fanotify() and Default() return a fallbackWatcher that catches it per request and retries on inotify automatically.","triggerScenarios":"Default() or Fanotify() on Linux with kernel 5.13+ watching a directory on overlayfs or virtiofs (the default inside many Docker containers) or FUSE-backed NTFS. Any custom routing that uses the raw fanotify backend on such mounts.","commonSituations":"Dev tools run inside Docker containers with overlay2 storage. Docker Desktop on macOS sharing code via virtiofs or gRPC FUSE. Dual-boot machines with NTFS data disks mounted through fuseblk.","solutions":["Use fswatch.Fanotify() or fswatch.Default(): both reroute unsupported directories to inotify automatically","If fanotify semantics are required, move the watched tree to a filesystem with FID support (ext4, xfs, btrfs)","When building your own fallback, key it on errors.Is(err, fswatch.ErrFilesystemUnsupported)","Run the watcher outside the container when the mount type cannot change"],"exampleFix":"// before\n// raw primary backend with no fallback routing\n\n// after\nw := fswatch.Fanotify() // fanotify + automatic inotify fallback\nwatch, err := w.WatchDirectory(dir, cb)","handlingStrategy":"fallback","validationCode":"// Prefer the auto-falling-back constructors:\nw := fswatch.Fanotify()   // fanotify primary, inotify secondary\n// or\nw := fswatch.Default()    // already the fallback watcher on Linux","typeGuard":"func isFilesystemUnsupported(err error) bool {\n    return errors.Is(err, fswatch.ErrFilesystemUnsupported)\n}","tryCatchPattern":"watch, err := primary.WatchDirectory(dir, cb)\nif errors.Is(err, fswatch.ErrFilesystemUnsupported) {\n    watch, err = fswatch.Inotify().WatchDirectory(dir, cb)\n}","preventionTips":["Inside Docker, expect overlayfs/virtiofs: use Fanotify() or Default() so inotify takes over","Key any custom fallback on errors.Is with ErrFilesystemUnsupported, not on message text","Check /proc/mounts for the backing filesystem when watch behavior differs across mounts","Run watchers outside the container when the mount type is fixed and unsupported"],"tags":["linux","fanotify","docker","fuse","overlayfs","filesystem"],"backgroundTag":null,"analyzedSha":"1bcfa18d79a3be41772223d5c05dfe4480e614ff","analyzedAt":"2026-08-16T02:12:00.115Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}