java-native-access/jna · error · RuntimeException
Service stop exceeded timeout time of
Error message
Service stop exceeded timeout time of %d ms
What it means
W32Service.stopService() polls the service status in a loop until it reports SERVICE_STOPPED. If the wall-clock time since the stop request exceeds the caller-supplied timeout while the service is still not STOPPED, it throws this RuntimeException so the caller knows the stop did not complete in time.
Solutions
- Increase the timeout argument to stopService to a value larger than the service's realistic shutdown time.
- Fix the service itself so its stop handler exits promptly (signal worker threads, use a cancellation mechanism).
- Check the service state manually (sc query / services.msc) to see whether it is stuck in STOP_PENDING and needs force-kill.
- Catch the RuntimeException and fall back to killing the process or waiting longer with a fresh request.
Example fix
// before service.stopService(1000); // after service.stopService(60_000); // allow slow shutdowns
Defensive patterns
Strategy: try-catch
Validate before calling
Winsvc.SERVICE_STATUS st = service.queryStatus();
if (st.dwCurrentState == Winsvc.SERVICE_STOPPED) { /* already stopped */ }
// choose timeout generously, e.g. max(30s, 2 * st.dwWaitHint) Try / catch
try {
service.stopService(timeoutMs);
} catch (RuntimeException e) {
Winsvc.SERVICE_STATUS st = service.queryStatus();
if (st.dwCurrentState != Winsvc.SERVICE_STOPPED) { /* escalate: kill or alert */ }
} Prevention
- Set timeouts well above the service's known shutdown time.
- Check dwWaitHint from queryStatus before choosing the timeout.
- Monitor services that routinely hit stop timeouts — fix the service, not the caller.
When it happens
Trigger: Calling stopService(timeoutMs) on a Windows service whose dwCurrentState stays non-STOPPED past the deadline — e.g. a service with a long OnStop handler, a hung/stuck service, or a timeout set too short for the service's shutdown work.
Common situations: Services that block shutdown waiting on worker threads or network I/O; SCM wait-hint values that understate real stop time; passing small (e.g. 1000 ms) timeouts to services that take tens of seconds to stop; debugging services in a paused or stop-pending state.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Timeout waiting for service to change to a non-pending…
- Got a WMI timeout when infinite wait was specified. This…
- No results after ms.
- Unable to continue the service
- Unable to pause the service
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/ba06446c82240983.
Report an issue: GitHub.
Appendix: source
Thrown at contrib/platform/src/com/sun/jna/platform/win32/W32Service.java:244
public void stopService(long timeout) {
long startTime = System.currentTimeMillis();
waitForNonPendingState();
// If the service is already stopped - return
if (queryStatus().dwCurrentState == Winsvc.SERVICE_STOPPED) {
return;
}
SERVICE_STATUS status = new SERVICE_STATUS();
if (!Advapi32.INSTANCE.ControlService(_handle, SERVICE_CONTROL_STOP, status)) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
// This following the sample from the MSDN
// the previouos implementation queried the service status and
// failed if the application did not correctly update its state
while (status.dwCurrentState != Winsvc.SERVICE_STOPPED) {
long msRemainingBeforeTimeout = timeout - (System.currentTimeMillis() - startTime);
if (msRemainingBeforeTimeout < 0) {
throw new RuntimeException(String.format("Service stop exceeded timeout time of %d ms", timeout));
}
long dwWaitTime = Math.min(sanitizeWaitTime(status.dwWaitHint), msRemainingBeforeTimeout);
try {
Thread.sleep(dwWaitTime);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (!Advapi32.INSTANCE.QueryServiceStatus(_handle, status)) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
}
}
/**
* Continue service.
*/View on GitHub (pinned to d036ad9781)