java-native-access/jna · error · RuntimeException

Failed to get printer change notification

Error message

Failed to get printer change notification - <errorCode>

What it means

Inside the monitor loop, FindNextPrinterChangeNotification is called to fetch the next printer-change event. If it returns FALSE, GetLastError is captured and a RuntimeException 'Failed to get printer change notification - <errorCode>' is thrown, aborting the monitoring loop mid-run.

Solutions

  1. Check errorCode: ERROR_INVALID_HANDLE (6) means the change handle is stale — re-open the printer and re-register with FindFirstPrinterChangeNotification.
  2. Catch the RuntimeException outside the while loop and rebuild the whole monitor (re-open handles) instead of terminating.
  3. Verify the PRINTER_NOTIFY_OPTIONS and info buffer pointer remain valid across iterations (don't free/reuse the buffer incorrectly).
  4. Ensure the account retains printer access for the duration of monitoring.

Example fix

// before
while (true) { ... FindNextPrinterChangeNotification(...); }
// after
while (running) {
    try {
        monitorOnce();
    } catch (RuntimeException e) {
        LOG.warn("Change notification failed, re-registering", e);
        closeHandles();
        reOpenAndRegister();
    }
}
Defensive patterns

Strategy: retry

Try / catch

boolean ok = Winspool.INSTANCE.FindNextPrinterChangeNotification(handle, change, options, infoPointer);
if (!ok) {
    int err = Kernel32.INSTANCE.GetLastError();
    if (err == W32Errors.ERROR_INVALID_HANDLE) { reRegisterMonitor(); }
}

Prevention

When it happens

Trigger: FindNextPrinterChangeNotification failing because the change handle became invalid (spooler restart, handle closed), the options/pointer arguments are malformed, or access was revoked while monitoring.

Common situations: Print Spooler service restarted or crashed while the monitor was running; long-running monitors losing their registration; passing an options struct the API rejects on subsequent calls.

Related errors


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

Appendix: source

Thrown at contrib/w32printing/src/com/sun/jna/platform/win32/Win32SpoolMonitor.java:152

            try {
                while (true) {
                    Kernel32.INSTANCE.WaitForSingleObject(
                        changeNotificationsHandle,
                        WinBase.INFINITE);

                    DWORDByReference change =
                        new DWORDByReference();
                    PointerByReference infoPointer = new PointerByReference();
                    success =
                        Winspool.INSTANCE.FindNextPrinterChangeNotification(
                            changeNotificationsHandle,
                            change,
                            options,
                            infoPointer);
                    if (!success) {
                        int errorCode = Kernel32.INSTANCE.GetLastError();
                        throw new RuntimeException("Failed to get printer " +
                            "change notification - " + errorCode);
                    }

                    System.out.println("Change - " +
                        String.format("0x%08X", change.getValue().longValue()));

                    if (infoPointer.getValue() != null) {
                        PRINTER_NOTIFY_INFO info =
                            Structure.newInstance(PRINTER_NOTIFY_INFO.class,
                                infoPointer.getValue());
                        info.read();

                        try {
                            if ((info.Flags & PRINTER_NOTIFY_INFO_DISCARDED) > 0) {
                                System.out.println("Some information was " +
                                    "discarded");
                            }

View on GitHub (pinned to d036ad9781)