{"record":{"id":"6f3e29b96678e9a8","repo":"java-native-access/jna","slug":"err","errorCode":"err","errorMessage":"ReadDirectoryChangesW failed on <file>: '<message>' (<err>)","messagePattern":"ReadDirectoryChangesW failed on <file>: '<message>' \\(<err>\\)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"contrib/platform/src/com/sun/jna/platform/win32/W32FileMonitor.java","lineNumber":118,"sourceCode":"            if (event != null) {\n                notify(event);\n            }\n\n            fni = fni.next();\n        } while (fni != null);\n\n        // trigger the next read\n        if (!finfo.file.exists()) {\n            unwatch(finfo.file);\n            return;\n        }\n\n        if (!klib.ReadDirectoryChangesW(finfo.handle, finfo.info,\n                finfo.info.size(), finfo.recursive, finfo.notifyMask,\n                finfo.infoLength, finfo.overlapped, null)) {\n            if (!disposing) {\n                int err = klib.GetLastError();\n                throw new IOException(\"ReadDirectoryChangesW failed on \"\n                        + finfo.file + \": '\"\n                        + Kernel32Util.formatMessageFromLastErrorCode(err)\n                        + \"' (\" + err + \")\");\n            }\n        }\n    }\n\n    private FileInfo waitForChange() {\n        IntByReference rcount = new IntByReference();\n        ULONG_PTRByReference rkey = new ULONG_PTRByReference();\n        PointerByReference roverlap = new PointerByReference();\n        if (! Kernel32.INSTANCE.GetQueuedCompletionStatus(port, rcount, rkey, roverlap, WinBase.INFINITE)) {\n            return null;\n        }\n        synchronized (this) {\n            return handleMap.get(new HANDLE(rkey.getValue().toPointer()));\n        }\n    }","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/java-native-access/jna/blob/d036ad9781adad4b66693e8fa7098e4ac665e0a3/contrib/platform/src/com/sun/jna/platform/win32/W32FileMonitor.java#L100-L136","documentation":"The background watcher thread of W32FileMonitor calls ReadDirectoryChangesW to register/change-buffer reads on the watched directory. When the native call fails (returns FALSE) while the monitor is not shutting down, an IOException with the formatted Win32 error message and code is thrown, aborting directory change monitoring for that file.","triggerScenarios":"The monitored directory handle becomes invalid (directory deleted/renamed, network share disconnected) while the monitor thread is running; the ReadDirectoryChangesW call inside handleChanges fails with a Win32 error such as ERROR_ACCESS_DENIED (5).","commonSituations":"Watching a directory on a removable or network drive that gets disconnected; the watched folder is deleted while the monitor is active; permission changes on the folder mid-watch.","solutions":["Catch the IOException from the monitor and re-register the watch once the directory is recreated/reconnected","Verify the watched directory exists and is accessible before and during monitoring","Use a local (non-network) directory when possible, as SMB shares commonly fail mid-watch","Stop the monitor explicitly when disposing to avoid spurious errors from the race with disposal"],"exampleFix":"// before\nW32FileMonitor monitor = new W32FileMonitor();\nmonitor.addWatch(dir, listener);\n// after\nW32FileMonitor monitor = new W32FileMonitor();\ntry {\n    monitor.addWatch(dir, listener);\n} catch (IOException e) {\n    // directory vanished or was denied; retry after ensuring it exists\n    if (dir.mkdirs()) monitor.addWatch(dir, listener);\n}","handlingStrategy":"try-catch","validationCode":"if (!dir.exists() || !dir.isDirectory()) {\n    throw new IllegalStateException(\"Watch target missing: \" + dir);\n}","typeGuard":null,"tryCatchPattern":"try {\n    monitor.addWatch(dir, listener);\n} catch (IOException e) {\n    // parse Win32 code from message, re-register or degrade to polling\n}","preventionTips":["Don't watch network/removable drives long-term","Stop the monitor before disposing to avoid shutdown races","Re-create the watch after the directory is recreated or reconnected"],"tags":["win32","file-monitoring","ioexception"],"backgroundTag":"file-read-failed","analyzedSha":"d036ad9781adad4b66693e8fa7098e4ac665e0a3","analyzedAt":"2026-09-12T06:50:59.239Z","contentChangedAt":"2026-09-12T06:50:59.239Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}