java-native-access/jna · error · Win32Exception

Win32Exception (error code from GetLastError after OpenPrint

Error message

Win32Exception (error code from GetLastError after OpenPrinter)

What it means

WinspoolUtil.getPrinterInfo2(String printerName) throws Win32Exception when the OpenPrinter call for the named printer fails. The exception carries Kernel32.INSTANCE.GetLastError(), most commonly ERROR_INVALID_PRINTER_NAME (1801) when the printer does not exist, or ERROR_ACCESS_DENIED when the caller lacks rights. Unlike errors 287/288 this happens before any EnumPrinters call, purely from resolving the printer name to a handle.

Source

Thrown at contrib/platform/src/com/sun/jna/platform/win32/WinspoolUtil.java:105

        }

        PRINTER_INFO_2 pPrinterEnum = new PRINTER_INFO_2(pcbNeeded.getValue());
        if (!Winspool.INSTANCE.EnumPrinters(flags, null, 2, pPrinterEnum.getPointer(), pcbNeeded.getValue(), pcbNeeded,
                pcReturned)) {
            throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
        }

        pPrinterEnum.read();
        return (PRINTER_INFO_2[]) pPrinterEnum.toArray(pcReturned.getValue());
    }

    public static PRINTER_INFO_2 getPrinterInfo2(String printerName) {
        IntByReference pcbNeeded = new IntByReference();
        IntByReference pcReturned = new IntByReference();
        HANDLEByReference pHandle = new HANDLEByReference();

        if (!Winspool.INSTANCE.OpenPrinter(printerName, pHandle, null)) {
            throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
        }

        Win32Exception we = null;
        PRINTER_INFO_2 pinfo2 = null;

        try {
            Winspool.INSTANCE.GetPrinter(pHandle.getValue(), 2, null, 0, pcbNeeded);
            if (pcbNeeded.getValue() <= 0) {
                return new PRINTER_INFO_2();
            }

            pinfo2 = new PRINTER_INFO_2(pcbNeeded.getValue());
            if (!Winspool.INSTANCE.GetPrinter(pHandle.getValue(), 2, pinfo2.getPointer(), pcbNeeded.getValue(), pcReturned)) {
                throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
            }

            pinfo2.read();
        } catch (Win32Exception e) {

View on GitHub (pinned to d036ad9781)

Solutions

  1. Verify the exact printer name via WinspoolUtil.getPrinterInfo1()/EnumPrinters or Control Panel, then pass it verbatim (including \\\\server\\share prefix for network printers)
  2. Check the Win32 code in the exception: 1801 = invalid name (fix the name), 5 = access denied (grant printer permissions)
  3. Trim/normalize the configured printer name before calling
  4. Catch Win32Exception and fall back to default printer or skip printer-specific logic

Example fix

// before
PRINTER_INFO_2 info = WinspoolUtil.getPrinterInfo2(cfgPrinter);
// after
PRINTER_INFO_2 info;
try {
    info = WinspoolUtil.getPrinterInfo2(cfgPrinter.trim());
} catch (Win32Exception e) {
    if (e.getErrorCode() == WinError.ERROR_INVALID_PRINTER_NAME) {
        info = null; // printer missing from config
    } else {
        throw e;
    }
}
Defensive patterns

Strategy: validation

Validate before calling

String name = cfgPrinter == null ? null : cfgPrinter.trim();
if (name == null || name.isEmpty()) {
    throw new IllegalArgumentException("printer name required");
}

Type guard

boolean printerNamePlausible(String n) {
    return n != null && !n.trim().isEmpty();
}

Try / catch

try {
    info = WinspoolUtil.getPrinterInfo2(name);
} catch (Win32Exception e) {
    if (e.getErrorCode() == WinError.ERROR_INVALID_PRINTER_NAME) {
        info = null; // unknown printer
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling getPrinterInfo2("name") with a name that is not an installed printer/share (typo, deleted printer, wrong server prefix like \\\\server\\printer), or without permission to open it.

Common situations: Hard-coded printer names that changed between machines/environments; reading a printer name from config with stale whitespace or wrong casing/server path; querying a network printer while offline or when the print server rejects the request.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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