java-native-access/jna · error · RuntimeException
Failed to access the print server
Error message
Failed to access the print server - <errorCode>
What it means
Win32SpoolMonitor.monitorAllPrinters() opens a handle to the local print server by calling OpenPrinter with a null printer name. If OpenPrinter fails, the last error code is read and a RuntimeException is thrown with the message 'Failed to access the print server - <errorCode>'. The monitor cannot attach to the spooler at all.
Solutions
- Check the errorCode: 5 (ERROR_ACCESS_DENIED) means run elevated or grant the account print-server permissions; 1722/RPC errors mean the spooler is unreachable.
- Start the Print Spooler service (net start spooler).
- Run the monitor in an interactive session or as a service account with print-operator rights.
- Catch the RuntimeException and degrade gracefully instead of crashing the demo/main flow.
Example fix
// before
Winspool.INSTANCE.OpenPrinter(null, printServerHandle, null);
// after
boolean success = Winspool.INSTANCE.OpenPrinter(null, printServerHandle, null);
if (!success) {
int err = Kernel32.INSTANCE.GetLastError();
if (err == W32Errors.ERROR_ACCESS_DENIED) {
LOG.error("Run elevated or grant print-server access to this account");
}
return;
} Defensive patterns
Strategy: try-catch
Validate before calling
boolean canOpenPrintServer() {
HANDLEByReference h = new HANDLEByReference();
boolean ok = Winspool.INSTANCE.OpenPrinter(null, h, null);
if (ok) { Winspool.INSTANCE.ClosePrinter(h.getValue()); }
return ok;
} Try / catch
try {
monitor.monitorAllPrinters();
} catch (RuntimeException e) {
LOG.error("Print-server access failed: " + e.getMessage()
+ " (run elevated / start spooler)");
} Prevention
- Run monitoring code elevated or with print-operator privileges.
- Ensure the spooler service is running before starting the monitor.
- Fail fast with a clear permission message when OpenPrinter fails.
- Use OpenPrinter(null,...) as an early probe for environment issues.
When it happens
Trigger: OpenPrinter(null, ...) returning FALSE, typically because the process has no permission to open the print server or the spooler service is not running.
Common situations: Running without administrator/elevated rights in a non-interactive session; Print Spooler service stopped; restricted service accounts lacking server-level printer access.
Related errors
- Failed to get a change handle
- Failed to get printer change notification
- Win32Exception (error code from GetLastError after EnumJobs)
- Win32Exception (error code from GetLastError after…
- Could not set proxy blanket.
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/4841098d70d7d2db.
Report an issue: GitHub.
Appendix: source
Thrown at contrib/w32printing/src/com/sun/jna/platform/win32/Win32SpoolMonitor.java:104
}
public int getLastError() {
int rc = Kernel32.INSTANCE.GetLastError();
if (rc != 0)
System.out.println("error: " + rc);
return rc;
}
public void monitorAllPrinters() {
System.out.println("Monitoring all printers, press Ctrl + C to stop");
HANDLEByReference printServerHandle = new HANDLEByReference();
boolean success =
Winspool.INSTANCE.OpenPrinter(null, printServerHandle, null);
if (!success) {
int errorCode = Kernel32.INSTANCE.GetLastError();
throw new RuntimeException("Failed to access the print server - " +
errorCode);
}
try {
PRINTER_NOTIFY_OPTIONS options = new PRINTER_NOTIFY_OPTIONS();
options.Count = 1;
PRINTER_NOTIFY_OPTIONS_TYPE.ByReference optionsType =
new PRINTER_NOTIFY_OPTIONS_TYPE.ByReference();
optionsType.Type = JOB_NOTIFY_TYPE;
optionsType.setFields(new short[] {
JOB_NOTIFY_FIELD_PRINTER_NAME,
JOB_NOTIFY_FIELD_STATUS,
JOB_NOTIFY_FIELD_DOCUMENT
});
optionsType.toArray(1);
options.pTypes = optionsType;
HANDLE changeNotificationsHandle =
Winspool.INSTANCE.FindFirstPrinterChangeNotification(View on GitHub (pinned to d036ad9781)