{"record":{"id":"6ecdd35782f895d0","repo":"java-native-access/jna","slug":"failed-to-get-a-change-handle-errorcode","errorCode":null,"errorMessage":"Failed to get a change handle - <errorCode>","messagePattern":"Failed to get a change handle - <errorCode>","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"contrib/w32printing/src/com/sun/jna/platform/win32/Win32SpoolMonitor.java","lineNumber":131,"sourceCode":"            optionsType.Type = JOB_NOTIFY_TYPE;\n            optionsType.setFields(new short[] {\n                JOB_NOTIFY_FIELD_PRINTER_NAME,\n                JOB_NOTIFY_FIELD_STATUS,\n                JOB_NOTIFY_FIELD_DOCUMENT\n            });\n            optionsType.toArray(1);\n            options.pTypes = optionsType;\n            HANDLE changeNotificationsHandle =\n                Winspool.INSTANCE.FindFirstPrinterChangeNotification(\n                    printServerHandle.getValue(),\n                    PRINTER_CHANGE_ADD_JOB |\n                        PRINTER_CHANGE_SET_JOB |\n                        PRINTER_CHANGE_DELETE_JOB,\n                    TWO_DIMENSIONAL_PRINTERS,\n                    options);\n            if (!isValidHandle(changeNotificationsHandle)) {\n                int errorCode = Kernel32.INSTANCE.GetLastError();\n                throw new RuntimeException(\"Failed to get a change handle - \" +\n                    errorCode);\n            }\n\n            try {\n                while (true) {\n                    Kernel32.INSTANCE.WaitForSingleObject(\n                        changeNotificationsHandle,\n                        WinBase.INFINITE);\n\n                    DWORDByReference change =\n                        new DWORDByReference();\n                    PointerByReference infoPointer = new PointerByReference();\n                    success =\n                        Winspool.INSTANCE.FindNextPrinterChangeNotification(\n                            changeNotificationsHandle,\n                            change,\n                            options,\n                            infoPointer);","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/java-native-access/jna/blob/d036ad9781adad4b66693e8fa7098e4ac665e0a3/contrib/w32printing/src/com/sun/jna/platform/win32/Win32SpoolMonitor.java#L113-L149","documentation":"monitorAllPrinters() calls FindFirstPrinterChangeNotification to obtain a change-notification handle for printer/job events. If the returned handle is not valid, the last error code is captured and a RuntimeException 'Failed to get a change handle - <errorCode>' is thrown. Without this handle the monitor cannot watch for printer changes.","triggerScenarios":"FindFirstPrinterChangeNotification returning INVALID_HANDLE_VALUE due to an invalid print-server handle, insufficient privileges for change notification, or a malformed PRINTER_NOTIFY_OPTIONS structure.","commonSituations":"Server handle was already closed or was null because a previous OpenPrinter failed silently; running without privileges to register change notifications on the spooler.","solutions":["Check errorCode: ERROR_ACCESS_DENIED (5) means run elevated or grant notification rights on the printer/server.","Verify the print-server handle from OpenPrinter was valid before calling FindFirstPrinterChangeNotification.","Validate the PRINTER_NOTIFY_OPTIONS fields/types match the loaded native structure (version/platform mismatches can corrupt the struct).","Retry after confirming the spooler service is healthy; catch RuntimeException to avoid crashing the monitor loop."],"exampleFix":"// before\nHANDLE h = Winspool.INSTANCE.FindFirstPrinterChangeNotification(...);\n// after\nHANDLE h = Winspool.INSTANCE.FindFirstPrinterChangeNotification(...);\nif (!isValidHandle(h)) {\n    int err = Kernel32.INSTANCE.GetLastError();\n    LOG.error(\"Change-handle registration failed (code \" + err + \"); check privileges/spooler\");\n    return;\n}","handlingStrategy":"validation","validationCode":"HANDLEByReference h = new HANDLEByReference();\nif (!Winspool.INSTANCE.OpenPrinter(null, h, null)) {\n    throw new IllegalStateException(\"Cannot open print server: \"\n        + Kernel32.INSTANCE.GetLastError());\n}","typeGuard":"boolean isValidChangeHandle(HANDLE h) {\n    return h != null && !h.equals(WinBase.INVALID_HANDLE_VALUE);\n}","tryCatchPattern":null,"preventionTips":["Always validate the OpenPrinter result before requesting a change handle.","Run with privileges allowing printer change notification registration.","Re-check handle validity each time before use.","Keep PRINTER_NOTIFY_OPTIONS struct fields consistent with the JNA mapping version."],"tags":["windows","printing","handle","runtime-exception"],"backgroundTag":"api-error-response","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"}