{"record":{"id":"59656d0f555628a3","repo":"microsoft/typescript-go","slug":"unable-to-initialize-fanotify-w","errorCode":null,"errorMessage":"unable to initialize fanotify: %w","messagePattern":"unable to initialize fanotify: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/fswatch/fanotify_linux.go","lineNumber":233,"sourceCode":"\t}\n\tb.pipeWriteFD.Store(-1)\n\tb.watcherBase.init(b)\n\treturn b\n}\n\nfunc (b *fanotifyBackend) start() error {\n\tif err := unix.Pipe2(b.pipeFDs[:], unix.O_CLOEXEC|unix.O_NONBLOCK); err != nil {\n\t\treturn fmt.Errorf(\"unable to open pipe: %w\", err)\n\t}\n\tb.pipeWriteFD.Store(int32(b.pipeFDs[1]))\n\tdefer func() {\n\t\tb.closeFDs()\n\t\tclose(b.endedSignal)\n\t}()\n\n\tfd, err := unix.FanotifyInit(fanotifyInitFlags, unix.O_RDONLY|unix.O_CLOEXEC)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to initialize fanotify: %w\", err)\n\t}\n\tb.fanotifyFD = fd\n\n\tpollfds := []unix.PollFd{\n\t\t{Fd: int32(b.pipeFDs[0]), Events: unix.POLLIN},\n\t\t{Fd: int32(b.fanotifyFD), Events: unix.POLLIN},\n\t}\n\n\tb.notifyStarted()\n\n\tfor {\n\t\t_, err := unix.Poll(pollfds, 500)\n\t\tif err != nil {\n\t\t\tif errors.Is(err, unix.EINTR) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn fmt.Errorf(\"unable to poll: %w\", err)\n\t\t}","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/microsoft/typescript-go/blob/1bcfa18d79a3be41772223d5c05dfe4480e614ff/internal/fswatch/fanotify_linux.go#L215-L251","documentation":"unix.FanotifyInit failed with FAN_CLASS_NOTIF|FAN_CLOEXEC|FAN_NONBLOCK|FAN_REPORT_FID|FAN_REPORT_DFID_NAME. The wrapped errno identifies why: ENOSYS/EINVAL on kernels without fanotify or without FID reporting (pre-5.1), EINVAL where the flag combination is unsupported, EPERM on kernels requiring CAP_SYS_ADMIN, EMFILE on fd exhaustion.","triggerScenarios":"Running on Linux < 5.1 (FAN_REPORT_FID requires 5.1; unprivileged FAN_CLASS_NOTIF notification groups require 5.13) — EINVAL/EPERM; kernel built without CONFIG_FANOTIFY — ENOSYS; old container runtimes/syscall filters; fd limit reached — EMFILE.","commonSituations":"Deploying to older LTS distros (Debian 10, CentOS 7, Ubuntu 18.04 kernels); WSL2 with outdated kernel; minimal VMs; CI images pinned to ancient kernels; unprivileged containers on host kernels between 5.1 and 5.13.","solutions":["Move to a kernel >= 5.13 (ideally current LTS) so unprivileged FID-based fanotify works","If stuck below 5.13, grant CAP_SYS_ADMIN to the process or run privileged","Fall back to another backend: fswatch.Inotify() (pure inotify) or a polling watcher","Check /proc/config.gz or `grep fanotify /boot/config-$(uname -r)` to confirm CONFIG_FANOTIFY=y"],"exampleFix":"// before\nw, err := fswatch.Default().WatchDirectory(dir, cb, fswatch.WithRecursive()) // fanotify init EINVAL on old kernel\n\n// after: pick a backend that the kernel supports\nwatcher := fswatch.Default()\nif watcher.Name() == \"fanotify\" && !kernelSupportsFanotify() {\n    watcher = fswatch.Inotify()\n}\nw, err := watcher.WatchDirectory(dir, cb, fswatch.WithRecursive())","handlingStrategy":"fallback","validationCode":"// Probe fanotify support before choosing the default backend on Linux.\nfunc fanotifyUsable() bool {\n    fd, err := unix.FanotifyInit(unix.FAN_CLASS_NOTIF|unix.FAN_CLOEXEC|unix.FAN_NONBLOCK|\n        unix.FAN_REPORT_FID|unix.FAN_REPORT_DFID_NAME, unix.O_RDONLY|unix.O_CLOEXEC)\n    if err != nil {\n        return false\n    }\n    unix.Close(fd)\n    return true\n}","typeGuard":"func isFanotifyInitFailure(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"unable to initialize fanotify\")\n}","tryCatchPattern":"w, err := fswatch.Default().WatchDirectory(dir, cb, opts...)\nif err != nil && isFanotifyInitFailure(err) {\n    // Kernel lacks fanotify FID support or privileges: switch backend.\n    w, err = fswatch.Inotify().WatchDirectory(dir, cb, opts...)\n}\nif err != nil { return err }","preventionTips":["Document a minimum kernel (>= 5.13 for unprivileged fanotify FID) and enforce it in deployment checks","In containers on hosts 5.1–5.13, add CAP_SYS_ADMIN or pre-select the inotify backend","Probe once at startup and cache the backend choice instead of failing per-watch"],"tags":["linux","fanotify","kernel-version","fswatch","permissions"],"backgroundTag":null,"analyzedSha":"1bcfa18d79a3be41772223d5c05dfe4480e614ff","analyzedAt":"2026-08-16T02:12:00.115Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}