apereo/cas · error · IllegalArgumentException
No state could be found to determine session state
Error message
No state could be found to determine session state
What it means
WsFederationCookieManager.retrieve() reconstructs the delegated-authentication session state from a serialized 'serverState' value taken from the request session (keyed by the identity-provider configuration id). If no non-blank state value can be found, CAS cannot correlate the callback with an in-flight WS-Federation sign-in and throws IllegalArgumentException to abort the flow.
Solutions
- Ensure the CAS session cookie survives the full WS-Federation round trip (SameSite settings, no cookie stripping, sticky sessions on the load balancer).
- Restart the delegated sign-in from the initial /login redirect instead of invoking the callback URL directly.
- Verify the WsFederation identity-provider configuration id is stable across nodes and restarts, since it names the state attribute/cookie.
- Increase session timeout or persist state out-of-session if IdP redirects are slow.
Example fix
// before
String serverState = cookieManager.retrieve(request);
// after
try {
String serverState = cookieManager.retrieve(request);
} catch (IllegalArgumentException e) {
LOGGER.warn("WS-Fed state missing; restarting delegated authentication", e);
response.sendRedirect(loginUrl);
} Defensive patterns
Strategy: try-catch
Validate before calling
HttpSession s = request.getSession(false);
Object st = (s != null) ? s.getAttribute(config.getId()) : null;
if (!(st instanceof String) || ((String) st).isBlank()) { /* restart delegated auth before calling retrieve */ } Type guard
boolean hasServerState(HttpServletRequest req, WsFederationIdentityProviderConfiguration cfg) {
HttpSession s = req.getSession(false);
return s != null && s.getAttribute(cfg.getId()) instanceof String st && !st.isBlank();
} Try / catch
try {
cookieManager.retrieve(request);
} catch (IllegalArgumentException e) {
// missing/blank WS-Fed state: restart the delegated sign-in redirect
} Prevention
- Always enter the flow via /login; never call the callback URL out of band.
- Ensure session cookies survive the IdP redirect (SameSite, sticky sessions).
- Monitor session timeouts versus slow IdP round trips.
- Keep the identity-provider configuration id stable across nodes.
When it happens
Trigger: retrieve() is invoked during WS-Federation callback handling but neither the session attribute named configuration.getId() nor the state cookie yields a non-blank string — e.g. the user hits the callback URL directly, the HTTP session expired during the IdP redirect, or cookies were dropped.
Common situations: Browsers blocking cookies (SameSite/third-party), load-balanced CAS without sticky sessions, session timeout between /login redirect and ADFS callback, users bookmarking or replaying callback URLs, or a changed configuration id making the state key unresolvable.
Related errors
- Unable to determine the [WA] parameter
- Denied
- Authentication request was denied from the provider
- Credential attributes do not include an attribute for
- Denied
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/69039bd593824042.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-wsfederation/src/main/java/org/apereo/cas/support/wsfederation/web/WsFederationCookieManager.java:70
throw new IllegalArgumentException("No " + WCTX + " parameter is found");
}
val configuration = configurations.stream()
.filter(cookie -> cookie.getId().equalsIgnoreCase(contextId))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("Could not locate WsFederation configuration for " + contextId));
val cookieGen = configuration.getCookieGenerator();
var serverState = cookieGen.retrieveCookieValue(request);
if (StringUtils.isBlank(serverState)) {
serverState = Optional.ofNullable(request.getSession(false))
.map(session -> session.getAttribute(configuration.getId()))
.map(String.class::cast)
.orElse(null);
}
if (StringUtils.isBlank(serverState)) {
LOGGER.error("No server state value could be retrieved to determine the state of the delegated authentication session");
throw new IllegalArgumentException("No state could be found to determine session state");
}
val blob = EncodingUtils.hexDecode(serverState);
val session = serializer.from(blob);
request.setAttribute(casProperties.getTheme().getParamName(), session.get(casProperties.getTheme().getParamName()));
request.setAttribute(casProperties.getLocale().getParamName(), session.get(casProperties.getLocale().getParamName()));
request.setAttribute(CasProtocolConstants.PARAMETER_METHOD, session.get(CasProtocolConstants.PARAMETER_METHOD));
val serviceKey = CasProtocolConstants.PARAMETER_SERVICE + '-' + contextId;
val service = (Service) session.get(serviceKey);
LOGGER.debug("Located service [{}] from session", service);
WebUtils.putServiceIntoFlowScope(context, service);
return service;
}
/**
* Store.
*
* @param request the requestView on GitHub (pinned to e7288fc434)