java-native-access/jna · error · IOException
klib.GetLastError()
klib.GetLastError()
Error message
Unable to open <file> (<GetLastError>)
What it means
W32FileMonitor.watch opens the directory with CreateFile (FILE_LIST_DIRECTORY) to monitor changes. If CreateFile returns INVALID_HANDLE_VALUE, an IOException containing the GetLastError code is thrown, meaning the directory could not be opened for change notification.
Solutions
- Check File.exists() and directory readability immediately before addWatch
- Run the application under an account with sufficient permissions for the target directory
- Handle the IOException and retry with a corrected/validated path
- Avoid watching network/removable paths that may be unavailable
Example fix
// before
monitor.addWatch(dir, listener);
// after
if (dir.exists() && dir.isDirectory()) {
try {
monitor.addWatch(dir, listener);
} catch (IOException e) {
// handle ERROR_ACCESS_DENIED etc.
}
} Defensive patterns
Strategy: validation
Validate before calling
if (!file.exists() || !file.isDirectory() || !file.canRead()) {
throw new IllegalArgumentException("Cannot watch: " + file);
} Try / catch
try {
monitor.addWatch(dir, listener);
} catch (IOException e) {
// GetLastError code is embedded in the message; handle access-denied explicitly
} Prevention
- Ensure the process account has read access to the directory
- Re-check existence right before addWatch (avoid TOCTOU races)
- Avoid paths with invalid characters or unresolved symlinks
When it happens
Trigger: CreateFile fails when opening the watch target: directory does not exist, access denied (ERROR_ACCESS_DENIED=5), invalid path characters, or the path maps to a file rather than a directory on an OS/handle combination that disallows it.
Common situations: Watching a directory the process lacks read permission for; race where the folder is deleted between the ancestor check and CreateFile; watching a mapped drive that is offline.
Understand the failure class
Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.
Related errors
- err
- No ancestor found for
- Bad volume GUID path format:
- Device context did not release properly.
- Expected GetTokenInformation to fail with…
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/ba1855df396554f1.
Report an issue: GitHub.
Appendix: source
Thrown at contrib/platform/src/com/sun/jna/platform/win32/W32FileMonitor.java:193
}
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);
// Existing port is returned
port = klib.CreateIoCompletionPort(handle, port, handle.getPointer(), 0);
if (WinBase.INVALID_HANDLE_VALUE.equals(port)) {
throw new IOException("Unable to create/use I/O Completion port "
+ "for " + file + " ("
+ klib.GetLastError() + ")");
}
// TODO: use FileIOCompletionRoutine callback method instead of a
// dedicated thread
if (!klib.ReadDirectoryChangesW(handle, finfo.info, finfo.info.size(),
recursive, notifyMask, finfo.infoLength,
finfo.overlapped, null)) {View on GitHub (pinned to d036ad9781)