microsoft/typescript-go · error

name_to_handle_at: %w

Error message

name_to_handle_at: %w

What it means

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.

Source

Thrown at internal/fswatch/fanotify_linux.go:359

			}
		}
		return nil
	}); err != nil {
		_ = b.closeWatch(w)
		return err
	}
	return nil
}

func (b *fanotifyBackend) markDir(w *dirWatch, path string, markPath string) error {
	if err := unix.FanotifyMark(b.fanotifyFD, fanotifyMarkAddFlags, b.markMask, unix.AT_FDCWD, markPath); err != nil {
		return maybeWrapUnsupportedFilesystem(err)
	}
	handle, _, err := unix.NameToHandleAt(unix.AT_FDCWD, markPath, 0)
	if err != nil {
		// Unmark since we can't track this directory without a handle.
		_ = unix.FanotifyMark(b.fanotifyFD, unix.FAN_MARK_REMOVE|unix.FAN_MARK_ONLYDIR, b.markMask, unix.AT_FDCWD, markPath)
		return maybeWrapUnsupportedFilesystem(fmt.Errorf("name_to_handle_at: %w", err))
	}
	var st unix.Statfs_t
	if err := unix.Statfs(markPath, &st); err != nil {
		_ = unix.FanotifyMark(b.fanotifyFD, unix.FAN_MARK_REMOVE|unix.FAN_MARK_ONLYDIR, b.markMask, unix.AT_FDCWD, markPath)
		return fmt.Errorf("statfs: %w", err)
	}
	key := makeFanotifyHandleKey(st.Fsid.Val, handle.Type(), handle.Bytes())
	sub := &fanotifySubscription{path: path, watchPath: markPath, dirWatch: w, key: key}
	b.subscriptions[key] = append(b.subscriptions[key], sub)
	return nil
}

func maybeWrapUnsupportedFilesystem(err error) error {
	if errors.Is(err, unix.EOPNOTSUPP) || errors.Is(err, unix.ENOTSUP) || errors.Is(err, unix.ENODEV) {
		return fmt.Errorf("%w: %w", err, ErrFilesystemUnsupported)
	}
	return err
}

View on GitHub (pinned to 1bcfa18d79)

Solutions

  1. Detect via errors.Is(err, fswatch.ErrFilesystemUnsupported) and use a different backend (inotify or polling) for that path
  2. Move the watched tree to a native filesystem (e.g. Linux ext4 volume instead of the shared mount)
  3. Reconfigure the sharing layer to a filesystem that supports file handles (e.g. NFS with exportfs support, native disk image)

Example fix

// before
w, err := fswatch.Default().WatchDirectory("/mnt/host_src", cb, fswatch.WithRecursive()) // name_to_handle_at EOPNOTSUPP

// after
w, err := fswatch.Default().WatchDirectory("/mnt/host_src", cb, fswatch.WithRecursive())
if err != nil && errors.Is(err, fswatch.ErrFilesystemUnsupported) {
    w, err = fswatch.Inotify().WatchDirectory("/mnt/host_src", cb, fswatch.WithRecursive())
}
Defensive patterns

Strategy: fallback

Validate before calling

// Cheap pre-flight: statfs the target and reject known-unsupported FUSE types.
func fsSupportsHandles(path string) bool {
    var st unix.Statfs_t
    if err := unix.Statfs(path, &st); err != nil { return false }
    // virtiofs / fuse / fuseblk magic numbers
    magic := uint64(st.Type) & 0xFFFF_FFFF_FFFF_FFFF
    switch magic {
    case 0x73757245 /* fuse */, 0x65735546 /* v9fs */, 0x564c4f42 /* virtiofs */:
        return false
    }
    return true
}

Type guard

func isUnsupportedFS(err error) bool {
    return err != nil && errors.Is(err, fswatch.ErrFilesystemUnsupported)
}

Try / catch

w, err := fswatch.Default().WatchDirectory(dir, cb, opts...)
if err != nil && isUnsupportedFS(err) {
    // name_to_handle_at failed: this fs cannot do FID watching. Use inotify or poll.
    if w, err = fswatch.Inotify().WatchDirectory(dir, cb, opts...); err != nil {
        return startPolling(dir, cb)
    }
}

Prevention

When it happens

Trigger: 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.

Common situations: Dev containers on macOS Docker Desktop / Podman machine sharing the workspace via FUSE; WSL2 mounts; CI runners checking out to FUSE-backed volumes.

Related errors


AI-assisted analysis of microsoft/typescript-go@1bcfa18d79 (2026-08-16). Data as JSON: /api/errors/cc8571514ee82aec. Report an issue: GitHub.