apereo/cas · error · IllegalArgumentException
Unable to find supported NameID format for service
Error message
Unable to find supported NameID format for service %s
What it means
When creating the NameID for a SAML single-logout response, SamlIdPProfileSingleLogoutMessageCreator.buildNameId iterates the configured NameID formats and tries to produce a NameID for the service; if every candidate fails or none applies, it throws this IllegalArgumentException. The IdP cannot determine a NameID format supported both by its configuration and the registered SAML service.
Solutions
- Add the SP-required format to the service's nameIdFormats in the SamlRegisteredService config
- Use a broadly supported format like urn:oasis:names:tc:SAML:2.0:nameid-format:transient if policy allows
- If persistent NameID is needed, configure and populate the persistent IdP/SP data store
- Check the SP metadata NameIDFormat list and align CAS service configuration with it
Example fix
// before (service registry JSON) "nameIdFormats": ["urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"] // after: include a format CAS can resolve without stored pairwise IDs "nameIdFormats": ["urn:oasis:names:tc:SAML:2.0:nameid-format:transient"]
Defensive patterns
Strategy: validation
Validate before calling
// confirm format intersection before invoking SLO NameID building
Set<String> supported = Set.of("urn:oasis:names:tc:SAML:2.0:nameid-format:transient");
if (spMetadataNameIdFormats.stream().noneMatch(supported::contains)) {
throw new ConfigurationException("No mutually supported NameID format for " + service.getServiceId());
} Prevention
- Set nameIdFormats explicitly on each SamlRegisteredService to match SP metadata
- Prefer transient format when persistent pairwise stores are not configured
- Keep SP metadata NameIDFormat lists and CAS config in sync during onboarding
When it happens
Trigger: nameId -> buildNameId for a SLO flow when the service's supported NameID formats (or the IdP's configured formats) yield no resolvable NameID — e.g. persistent NameID requested but no matching persistent IdP/SP pair stored, or no format intersection between IdP and SP metadata.
Common situations: SP metadata requests a NameID format CAS is not configured to produce (transient/persistent/emailAddress mismatch); nameIdFormats not set on the SamlRegisteredService so defaults don't match; persistent NameID store (data store) missing the pairwise ID for the user/SP pair.
Related errors
- Logout request is not signed but should be for service
- Assertion will skip assigning/generating a nameId based on…
- Required NameID format
- No NameID could be determined based on the supported formats
- No Certificates provided
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/93fa3dc0332981fd.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-saml-idp-web/src/main/java/org/apereo/cas/support/saml/web/idp/profile/slo/SamlIdPProfileSingleLogoutMessageCreator.java:126
if (effectiveNameIdFormats.isEmpty()) {
effectiveNameIdFormats.add(NameIDType.UNSPECIFIED);
}
for (val nameFormat : effectiveNameIdFormats) {
try {
val nameIdValue = buildLogoutRequestNameId(request, nameFormat);
val encoder = SamlAttributeBasedNameIdGenerator.get(Optional.empty(), nameFormat, samlService, nameIdValue);
LOGGER.debug("Encoding NameID based on [{}]", nameFormat);
val nameId = encoder.generate(new ProfileRequestContext(), nameFormat);
if (nameId != null) {
LOGGER.debug("Generated NameID [{}] with format [{}]", nameId.getValue(), nameFormat);
return nameId;
}
} catch (final Exception e) {
LoggingUtils.error(LOGGER, e);
}
}
throw new IllegalArgumentException("Unable to find supported NameID format for service %s".formatted(samlService.getServiceId()));
}
protected boolean shouldSignLogoutRequestFor(final SamlRegisteredService registeredService) {
val samlIdPProperties = samlProfileHandlerConfigurationContext.getCasProperties().getAuthn().getSamlIdp();
return registeredService.getSignLogoutRequest().isUndefined()
? samlIdPProperties.getLogout().isForceSignedLogoutRequests()
: registeredService.getSignLogoutRequest().isTrue();
}
protected String buildLogoutRequestNameId(final SingleLogoutRequestContext request, final String nameIdFormat) throws Throwable {
val samlService = (SamlRegisteredService) request.getRegisteredService();
LOGGER.debug("Preparing NameID attribute for SAML service [{}] with format [{}]", samlService.getName(), nameIdFormat);
val principal = request.getExecutionRequest().getTicketGrantingTicket()
.getAuthentication().getPrincipal();
if (NameIDType.TRANSIENT.equalsIgnoreCase(StringUtils.trim(nameIdFormat))) {
val serviceId = request.getService().getId();
val resolver = samlProfileHandlerConfigurationContext.getSamlRegisteredServiceCachingMetadataResolver();
val adaptorRes = SamlRegisteredServiceMetadataAdaptor.get(resolver, samlService, serviceId);View on GitHub (pinned to e7288fc434)