java-native-access/jna · error · FileNotFoundException

No ancestor found for

Error message

No ancestor found for <file>

What it means

W32FileMonitor.watch walks up the parent chain of the requested file to find the nearest existing ancestor directory to watch (marking recursive=true). If it climbs all the way to the root and no ancestor exists, it throws FileNotFoundException because there is no valid directory to pass to CreateFile.

Solutions

  1. Ensure at least the parent directory (or the drive root) of the target path exists before calling addWatch
  2. Create the missing ancestor directories yourself, then add the watch
  3. Validate the path (drive letter, UNC host/share availability) before registering the watch
  4. Catch FileNotFoundException and surface a clear message to the user about the invalid watch path

Example fix

// before
monitor.addWatch(new File("X:\\missing\\sub"), listener);
// after
File dir = new File("X:\\missing\\sub");
if (dir.getParentFile() == null || !dir.getParentFile().exists()) {
    throw new IllegalArgumentException("Watch path has no existing ancestor: " + dir);
}
monitor.addWatch(dir, listener);
Defensive patterns

Strategy: validation

Validate before calling

File dir = file.getAbsoluteFile();
while (dir != null && !dir.exists()) { dir = dir.getParentFile(); }
if (dir == null) throw new IllegalArgumentException("No existing ancestor for " + file);

Prevention

When it happens

Trigger: Calling W32FileMonitor.addWatch with a path whose every ancestor is non-existent (e.g. a deeply nested path on a drive/mount point that does not exist, or a malformed path like 'Z:\nonexistent-drive\a\b').

Common situations: Typos in drive letters or UNC paths; watching a path on a disconnected network share; watching a path under a mount point that is not mounted yet.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12). Data as JSON: /api/errors/cf010241137042a3. Report an issue: GitHub.

Appendix: source

Thrown at contrib/platform/src/com/sun/jna/platform/win32/W32FileMonitor.java:181

        }
        return result;
    }

    private static int watcherThreadID;

    @Override
    protected synchronized void watch(File file, int eventMask, boolean recursive) throws IOException {
        File dir = file;
        if (!dir.isDirectory()) {
            recursive = false;
            dir = file.getParentFile();
        }
        while (dir != null && !dir.exists()) {
            recursive = true;
            dir = dir.getParentFile();
        }
        if (dir == null) {
            throw new FileNotFoundException("No ancestor found for " + file);
        }
        Kernel32 klib = Kernel32.INSTANCE;
        int mask = WinNT.FILE_SHARE_READ
            | WinNT.FILE_SHARE_WRITE | WinNT.FILE_SHARE_DELETE;
        int flags = WinNT.FILE_FLAG_BACKUP_SEMANTICS
            | WinNT.FILE_FLAG_OVERLAPPED;
        HANDLE handle = klib.CreateFile(file.getAbsolutePath(),
                WinNT.FILE_LIST_DIRECTORY,
                mask, null, WinNT.OPEN_EXISTING,
                flags, null);
        if (WinBase.INVALID_HANDLE_VALUE.equals(handle)) {
            throw new IOException("Unable to open " + file + " ("
                                  + klib.GetLastError() + ")");
        }
        int notifyMask = convertMask(eventMask);
        FileInfo finfo = new FileInfo(file, handle, notifyMask, recursive);
        fileMap.put(file, finfo);
        handleMap.put(handle, finfo);

View on GitHub (pinned to d036ad9781)