{"record":{"id":"93fa3dc0332981fd","repo":"apereo/cas","slug":"unable-to-find-supported-nameid-format-for-service","errorCode":null,"errorMessage":"Unable to find supported NameID format for service %s","messagePattern":"Unable to find supported NameID format for service (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"support/cas-server-support-saml-idp-web/src/main/java/org/apereo/cas/support/saml/web/idp/profile/slo/SamlIdPProfileSingleLogoutMessageCreator.java","lineNumber":126,"sourceCode":"        if (effectiveNameIdFormats.isEmpty()) {\n            effectiveNameIdFormats.add(NameIDType.UNSPECIFIED);\n        }\n\n        for (val nameFormat : effectiveNameIdFormats) {\n            try {\n                val nameIdValue = buildLogoutRequestNameId(request, nameFormat);\n                val encoder = SamlAttributeBasedNameIdGenerator.get(Optional.empty(), nameFormat, samlService, nameIdValue);\n                LOGGER.debug(\"Encoding NameID based on [{}]\", nameFormat);\n                val nameId = encoder.generate(new ProfileRequestContext(), nameFormat);\n                if (nameId != null) {\n                    LOGGER.debug(\"Generated NameID [{}] with format [{}]\", nameId.getValue(), nameFormat);\n                    return nameId;\n                }\n            } catch (final Exception e) {\n                LoggingUtils.error(LOGGER, e);\n            }\n        }\n        throw new IllegalArgumentException(\"Unable to find supported NameID format for service %s\".formatted(samlService.getServiceId()));\n    }\n\n    protected boolean shouldSignLogoutRequestFor(final SamlRegisteredService registeredService) {\n        val samlIdPProperties = samlProfileHandlerConfigurationContext.getCasProperties().getAuthn().getSamlIdp();\n        return registeredService.getSignLogoutRequest().isUndefined()\n            ? samlIdPProperties.getLogout().isForceSignedLogoutRequests()\n            : registeredService.getSignLogoutRequest().isTrue();\n    }\n\n    protected String buildLogoutRequestNameId(final SingleLogoutRequestContext request, final String nameIdFormat) throws Throwable {\n        val samlService = (SamlRegisteredService) request.getRegisteredService();\n        LOGGER.debug(\"Preparing NameID attribute for SAML service [{}] with format [{}]\", samlService.getName(), nameIdFormat);\n        val principal = request.getExecutionRequest().getTicketGrantingTicket()\n            .getAuthentication().getPrincipal();\n        if (NameIDType.TRANSIENT.equalsIgnoreCase(StringUtils.trim(nameIdFormat))) {\n            val serviceId = request.getService().getId();\n            val resolver = samlProfileHandlerConfigurationContext.getSamlRegisteredServiceCachingMetadataResolver();\n            val adaptorRes = SamlRegisteredServiceMetadataAdaptor.get(resolver, samlService, serviceId);","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-saml-idp-web/src/main/java/org/apereo/cas/support/saml/web/idp/profile/slo/SamlIdPProfileSingleLogoutMessageCreator.java#L108-L144","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before (service registry JSON)\n\"nameIdFormats\": [\"urn:oasis:names:tc:SAML:2.0:nameid-format:persistent\"]\n// after: include a format CAS can resolve without stored pairwise IDs\n\"nameIdFormats\": [\"urn:oasis:names:tc:SAML:2.0:nameid-format:transient\"]","handlingStrategy":"validation","validationCode":"// confirm format intersection before invoking SLO NameID building\nSet<String> supported = Set.of(\"urn:oasis:names:tc:SAML:2.0:nameid-format:transient\");\nif (spMetadataNameIdFormats.stream().noneMatch(supported::contains)) {\n    throw new ConfigurationException(\"No mutually supported NameID format for \" + service.getServiceId());\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["saml","nameid","single-logout","service-config"],"backgroundTag":"nameid-format-not-supported","analyzedSha":"e7288fc434b4f4505b8452e1a57e8fb3111bb863","analyzedAt":"2026-09-08T15:39:16.015Z","contentChangedAt":"2026-09-08T15:39:16.015Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}