apereo/cas · warning · FailedLoginException
Thread interrupted while waiting for connection to validate…
Error message
Thread interrupted while waiting for connection to validate SPNEGO Token
What it means
While waiting to borrow a connection from the SPNEGO authentications pool, the calling thread received InterruptedException; the handler converts this into FailedLoginException. It indicates the thread was interrupted during pool.poll(), typically during server shutdown or executor termination.
Solutions
- Retry the authentication once the server is stable; this is usually transient during shutdown.
- Ensure clean shutdown ordering so login requests complete before pool/executor teardown.
- Check for overly aggressive request-timeout or thread-interruption policies in the servlet container/proxy.
- Investigate thread leaks that keep threads blocked in the pool and force interrupt-based cleanup.
Defensive patterns
Strategy: retry
Try / catch
try {
return handler.authenticate(credential);
} catch (FailedLoginException e) {
if (e.getMessage().contains("Thread interrupted")) {
LOGGER.warn("SPNEGO auth interrupted; retry after shutdown/deploy completes");
}
throw e;
} Prevention
- Avoid deploying during login-heavy windows
- Verify shutdown hooks drain in-flight requests before closing pools
- Check proxy/servlet-container timeout settings that interrupt worker threads
When it happens
Trigger: CAS shutdown/redeployment while SPNEGO logins are in flight; the request thread's executor is shutting down; manual thread interruption (e.g. request timeout killer) hitting a thread blocked in poll().
Common situations: Graceful shutdown under load; container orchestrator terminating pods; long-running blocked threads interrupted by timeouts.
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.
Related errors
- Cannot get connection from pool to validate SPNEGO Token
- NTLM not allowed
- Principal is null, the processing of the SPNEGO Token failed
- User Agent header [ ] is empty, or no browsers are supported
- SPNEGO Authorization header is not found under
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/430f26781edc2ec4.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-spnego/src/main/java/org/apereo/cas/support/spnego/authentication/handler/support/JcifsSpnegoAuthenticationHandler.java:68
if (!spnegoProperties.isNtlmAllowed() && spnegoCredential.isNtlm()) {
throw new FailedLoginException("NTLM not allowed");
}
try {
LOGGER.debug("Waiting for connection to validate SPNEGO Token");
val poolTimeoutInMilliseconds = Beans.newDuration(spnegoProperties.getPoolTimeout()).toMillis();
val authentications = authenticationsPool.poll(poolTimeoutInMilliseconds, TimeUnit.MILLISECONDS);
if (authentications != null) {
try {
return doInternalAuthentication(authentications, spnegoCredential, service);
} finally {
authenticationsPool.add(authentications);
LOGGER.debug("Returned connection to pool");
}
}
throw new FailedLoginException("Cannot get connection from pool to validate SPNEGO Token");
} catch (final InterruptedException e) {
throw new FailedLoginException("Thread interrupted while waiting for connection to validate SPNEGO Token");
}
}
protected AuthenticationHandlerExecutionResult doInternalAuthentication(final List<Authentication> authentications,
final SpnegoCredential spnegoCredential, final Service service) throws Throwable {
var principal = (java.security.Principal) null;
var nextToken = (byte[]) null;
val it = authentications.iterator();
while (nextToken == null && it.hasNext()) {
try {
val authentication = it.next();
authentication.reset();
LOGGER.debug("Processing SPNEGO authentication");
authentication.process(spnegoCredential.getInitToken());
principal = authentication.getPrincipal();
LOGGER.debug("Authenticated SPNEGO principal [{}]. Retrieving the next token for authentication...",
Optional.ofNullable(principal).map(java.security.Principal::getName).orElse(null));
nextToken = authentication.getNextToken();View on GitHub (pinned to e7288fc434)