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
- Verify the exact printer name via WinspoolUtil.getPrinterInfo1()/EnumPrinters or Control Panel, then pass it verbatim (including \\\\server\\share prefix for network printers)
- Check the Win32 code in the exception: 1801 = invalid name (fix the name), 5 = access denied (grant printer permissions)
- Trim/normalize the configured printer name before calling
- 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
- Resolve printer names dynamically via EnumPrinters instead of hard-coding
- Trim and normalize configured names; keep \\\\server\\share format for network printers
- Check error code 1801 vs 5 to distinguish missing name from access denied
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
- Win32Exception (error code from GetLastError after EnumPrint
- LookupAccountNameW was expected to fail with ERROR_INSUFFICI
- Expected GetTokenInformation to fail with ERROR_INSUFFICIENT
- Unexpected registry type + lpType.getValue() + , expected RE
- Invalid type:
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/848ac39cd9bf0ca7.
Report an issue: GitHub.