{"record":{"id":"cc8571514ee82aec","repo":"microsoft/typescript-go","slug":"name-to-handle-at-w","errorCode":null,"errorMessage":"name_to_handle_at: %w","messagePattern":"name_to_handle_at: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/fswatch/fanotify_linux.go","lineNumber":359,"sourceCode":"\t\t\t}\n\t\t}\n\t\treturn nil\n\t}); err != nil {\n\t\t_ = b.closeWatch(w)\n\t\treturn err\n\t}\n\treturn nil\n}\n\nfunc (b *fanotifyBackend) markDir(w *dirWatch, path string, markPath string) error {\n\tif err := unix.FanotifyMark(b.fanotifyFD, fanotifyMarkAddFlags, b.markMask, unix.AT_FDCWD, markPath); err != nil {\n\t\treturn maybeWrapUnsupportedFilesystem(err)\n\t}\n\thandle, _, err := unix.NameToHandleAt(unix.AT_FDCWD, markPath, 0)\n\tif err != nil {\n\t\t// Unmark since we can't track this directory without a handle.\n\t\t_ = unix.FanotifyMark(b.fanotifyFD, unix.FAN_MARK_REMOVE|unix.FAN_MARK_ONLYDIR, b.markMask, unix.AT_FDCWD, markPath)\n\t\treturn maybeWrapUnsupportedFilesystem(fmt.Errorf(\"name_to_handle_at: %w\", err))\n\t}\n\tvar st unix.Statfs_t\n\tif err := unix.Statfs(markPath, &st); err != nil {\n\t\t_ = unix.FanotifyMark(b.fanotifyFD, unix.FAN_MARK_REMOVE|unix.FAN_MARK_ONLYDIR, b.markMask, unix.AT_FDCWD, markPath)\n\t\treturn fmt.Errorf(\"statfs: %w\", err)\n\t}\n\tkey := makeFanotifyHandleKey(st.Fsid.Val, handle.Type(), handle.Bytes())\n\tsub := &fanotifySubscription{path: path, watchPath: markPath, dirWatch: w, key: key}\n\tb.subscriptions[key] = append(b.subscriptions[key], sub)\n\treturn nil\n}\n\nfunc maybeWrapUnsupportedFilesystem(err error) error {\n\tif errors.Is(err, unix.EOPNOTSUPP) || errors.Is(err, unix.ENOTSUP) || errors.Is(err, unix.ENODEV) {\n\t\treturn fmt.Errorf(\"%w: %w\", err, ErrFilesystemUnsupported)\n\t}\n\treturn err\n}","sourceCodeStart":341,"sourceCodeEnd":377,"githubUrl":"https://github.com/microsoft/typescript-go/blob/1bcfa18d79a3be41772223d5c05dfe4480e614ff/internal/fswatch/fanotify_linux.go#L341-L377","documentation":"After successfully fanotify-marking a directory, the backend needs a stable handle (name_to_handle_at) to build the FID subscription key mapping events back to watches. If the syscall fails, the mark is rolled back and the error is wrapped; EOPNOTSUPP/ENOTSUP/ENODEV (filesystems without exportable file handles) are additionally wrapped in ErrFilesystemUnsupported.","triggerScenarios":"Watching directories on filesystems that do not support file handles: Docker bind mounts over virtiofs, gRPC FUSE (macOS file sharing), some NFS configs, overlayfs — EOPNOTSUPP; NTFS via fuseblk — ENODEV; EPERM where CAP_DAC_READ_SEARCH is required to open handles on some filesystems.","commonSituations":"Dev containers on macOS Docker Desktop / Podman machine sharing the workspace via FUSE; WSL2 mounts; CI runners checking out to FUSE-backed volumes.","solutions":["Detect via errors.Is(err, fswatch.ErrFilesystemUnsupported) and use a different backend (inotify or polling) for that path","Move the watched tree to a native filesystem (e.g. Linux ext4 volume instead of the shared mount)","Reconfigure the sharing layer to a filesystem that supports file handles (e.g. NFS with exportfs support, native disk image)"],"exampleFix":"// before\nw, err := fswatch.Default().WatchDirectory(\"/mnt/host_src\", cb, fswatch.WithRecursive()) // name_to_handle_at EOPNOTSUPP\n\n// after\nw, err := fswatch.Default().WatchDirectory(\"/mnt/host_src\", cb, fswatch.WithRecursive())\nif err != nil && errors.Is(err, fswatch.ErrFilesystemUnsupported) {\n    w, err = fswatch.Inotify().WatchDirectory(\"/mnt/host_src\", cb, fswatch.WithRecursive())\n}","handlingStrategy":"fallback","validationCode":"// Cheap pre-flight: statfs the target and reject known-unsupported FUSE types.\nfunc fsSupportsHandles(path string) bool {\n    var st unix.Statfs_t\n    if err := unix.Statfs(path, &st); err != nil { return false }\n    // virtiofs / fuse / fuseblk magic numbers\n    magic := uint64(st.Type) & 0xFFFF_FFFF_FFFF_FFFF\n    switch magic {\n    case 0x73757245 /* fuse */, 0x65735546 /* v9fs */, 0x564c4f42 /* virtiofs */:\n        return false\n    }\n    return true\n}","typeGuard":"func isUnsupportedFS(err error) bool {\n    return err != nil && errors.Is(err, fswatch.ErrFilesystemUnsupported)\n}","tryCatchPattern":"w, err := fswatch.Default().WatchDirectory(dir, cb, opts...)\nif err != nil && isUnsupportedFS(err) {\n    // name_to_handle_at failed: this fs cannot do FID watching. Use inotify or poll.\n    if w, err = fswatch.Inotify().WatchDirectory(dir, cb, opts...); err != nil {\n        return startPolling(dir, cb)\n    }\n}","preventionTips":["On macOS Docker/Podman, keep source on the VM's native fs or plan an inotify/poll fallback for bind mounts","Check errors.Is(err, fswatch.ErrFilesystemUnsupported) — the library defines it exactly for this branch","Don't retry the same backend on the same mount: EOPNOTSUPP is permanent for that filesystem"],"tags":["linux","fanotify","fuse","docker","file-handles","fswatch"],"backgroundTag":null,"analyzedSha":"1bcfa18d79a3be41772223d5c05dfe4480e614ff","analyzedAt":"2026-08-16T02:12:00.115Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}