From 351d9a610ccb48a046937a2ba942b1d73d0049b7 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Wed, 4 Nov 2026 12:14:26 -0800 Subject: [PATCH 1/2] Fall back to inotify when fanotify rejects mounts with EXDEV Fanotify FID groups can reject watches spanning incompatible mounts with EXDEV, including virtiofs mounts. Treating this as fatal prevents watch mode from receiving any file changes despite inotify being usable. Fixes 65290. --- tsc/internal/fswatch/fanotify_linux.go | 3 ++- tsc/internal/fswatch/fanotify_linux_test.go | 16 +++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/tsc/internal/fswatch/fanotify_linux.go b/tsc/internal/fswatch/fanotify_linux.go index 1e4200afda52e..cff9225d060ec 100644 --- a/tsc/internal/fswatch/fanotify_linux.go +++ b/tsc/internal/fswatch/fanotify_linux.go @@ -370,7 +370,8 @@ func (b *fanotifyBackend) markDir(w *dirWatch, path string, markPath string) err } func maybeWrapUnsupportedFilesystem(err error) error { - if errors.Is(err, unix.EOPNOTSUPP) || errors.Is(err, unix.ENOTSUP) || errors.Is(err, unix.ENODEV) { + // EXDEV can also indicate incompatible mounts within a FID-based group. + if errors.Is(err, unix.EOPNOTSUPP) || errors.Is(err, unix.ENOTSUP) || errors.Is(err, unix.ENODEV) || errors.Is(err, unix.EXDEV) { return fmt.Errorf("%w: %w", err, ErrFilesystemUnsupported) } return err diff --git a/tsc/internal/fswatch/fanotify_linux_test.go b/tsc/internal/fswatch/fanotify_linux_test.go index 7dfe9f5825bbb..0bf7672c36754 100644 --- a/tsc/internal/fswatch/fanotify_linux_test.go +++ b/tsc/internal/fswatch/fanotify_linux_test.go @@ -127,13 +127,15 @@ func TestLinuxFanotifyMaybeWrapUnsupportedFilesystem(t *testing.T) { // Errnos that indicate the filesystem cannot support fanotify FID-based // watching are tagged with ErrFilesystemUnsupported so higher layers can // fall back to inotify (issue #63646). - for _, errno := range []error{unix.EOPNOTSUPP, unix.ENODEV} { - wrapped := maybeWrapUnsupportedFilesystem(fmt.Errorf("name_to_handle_at: %w", errno)) - if !errors.Is(wrapped, ErrFilesystemUnsupported) { - t.Errorf("expected %v to be tagged ErrFilesystemUnsupported", errno) - } - if !errors.Is(wrapped, errno) { - t.Errorf("expected wrapped error to still unwrap to %v", errno) + for _, errno := range []error{unix.EOPNOTSUPP, unix.ENODEV, unix.EXDEV} { + for _, err := range []error{errno, fmt.Errorf("name_to_handle_at: %w", errno)} { + wrapped := maybeWrapUnsupportedFilesystem(err) + if !errors.Is(wrapped, ErrFilesystemUnsupported) { + t.Errorf("expected %v to be tagged ErrFilesystemUnsupported", err) + } + if !errors.Is(wrapped, errno) { + t.Errorf("expected wrapped error to still unwrap to %v", errno) + } } } From 702b17592e15283c236dc27d1b6b7a4105fdaa84 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Wed, 4 Nov 2026 12:15:49 -0800 Subject: [PATCH 2/2] Remove redundant fanotify fallback comment --- tsc/internal/fswatch/fanotify_linux.go | 1 - 1 file changed, 1 deletion(-) diff --git a/tsc/internal/fswatch/fanotify_linux.go b/tsc/internal/fswatch/fanotify_linux.go index cff9225d060ec..692ac38ccee5e 100644 --- a/tsc/internal/fswatch/fanotify_linux.go +++ b/tsc/internal/fswatch/fanotify_linux.go @@ -370,7 +370,6 @@ func (b *fanotifyBackend) markDir(w *dirWatch, path string, markPath string) err } func maybeWrapUnsupportedFilesystem(err error) error { - // EXDEV can also indicate incompatible mounts within a FID-based group. if errors.Is(err, unix.EOPNOTSUPP) || errors.Is(err, unix.ENOTSUP) || errors.Is(err, unix.ENODEV) || errors.Is(err, unix.EXDEV) { return fmt.Errorf("%w: %w", err, ErrFilesystemUnsupported) }