{"record":{"id":"c9e88ab5723f7b55","repo":"apereo/cas","slug":"principal-resolution-is-set-to-resolve-users-via-a","errorCode":null,"errorMessage":"Principal resolution is set to resolve users via attribute(s) [{}], and yet the collection of attributes retrieved [{}] do not contain any of those attributes. This is likely due to misconfiguration and CAS will use [{}] as the final principal id","messagePattern":"Principal resolution is set to resolve users via attribute\\(s\\) \\[(.+?)\\], and yet the collection of attributes retrieved \\[(.+?)\\] do not contain any of those attributes\\. This is likely due to misconfiguration and CAS will use \\[(.+?)\\] as the final principal id","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"support/cas-server-support-person-directory-core/src/main/java/org/apereo/cas/authentication/principal/resolvers/PersonDirectoryPrincipalResolver.java","lineNumber":151,"sourceCode":"            val attrNames = org.springframework.util.StringUtils.commaDelimitedListToSet(context.getPrincipalAttributeNames());\n\n            val principalIdAttributes = new LinkedHashMap<>(attributes);\n            if (context.isUseCurrentPrincipalId() && currentPrincipal.isPresent()) {\n                val currentPrincipalAttributes = currentPrincipal.get().getAttributes();\n                LOGGER.trace(\"Merging current principal attributes [{}] with resolved attributes [{}]\",\n                    currentPrincipalAttributes, principalIdAttributes);\n                context.getAttributeMerger().mergeAttributes(principalIdAttributes, currentPrincipalAttributes);\n            }\n\n            LOGGER.debug(\"Using principal attributes [{}] to determine principal id\", principalIdAttributes);\n            val result = attrNames.stream()\n                .map(String::trim)\n                .filter(principalIdAttributes::containsKey)\n                .map(principalIdAttributes::get)\n                .findFirst();\n\n            if (result.isEmpty()) {\n                LOGGER.warn(\"Principal resolution is set to resolve users via attribute(s) [{}], and yet \"\n                        + \"the collection of attributes retrieved [{}] do not contain any of those attributes. This is \"\n                        + \"likely due to misconfiguration and CAS will use [{}] as the final principal id\",\n                    context.getPrincipalAttributeNames(), principalIdAttributes.keySet(), principalId);\n                builder.success(false);\n            } else {\n                val values = result.get();\n                if (!values.isEmpty()) {\n                    principalId = CollectionUtils.firstElement(values).map(Object::toString).orElseThrow();\n                    LOGGER.debug(\"Found principal id attribute value [{}]\", principalId);\n                }\n            }\n        }\n        return builder.principalId(principalId).attributes(convertedAttributes).build();\n    }\n\n    protected Map<String, List<Object>> retrievePersonAttributes(final String principalId,\n                                                                 final Credential credential,\n                                                                 final Optional<Principal> currentPrincipal,","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-person-directory-core/src/main/java/org/apereo/cas/authentication/principal/resolvers/PersonDirectoryPrincipalResolver.java#L133-L169","documentation":"During principal construction CAS was configured to derive the principal id from specific attributes (principalAttributeNames), but none of those attributes were present in the attribute bundle retrieved from the attribute repository. CAS falls back to the default principal id (usually the username) and marks the resolution as a non-success. This warn signals that the attribute-source configuration and the principalAttributeNames setting disagree.","triggerScenarios":"PersonDirectoryPrincipalResolver.convertPersonAttributesToPrincipal is invoked with context.getPrincipalAttributeNames() set (e.g. cas.authn.attributeRepository.core.principalAttributeNames=mail), but the resolved attribute map contains no key matching any of those names after trimming.","commonSituations":"LDAP attribute renamed (mail vs emailAddress); attribute not requested/released by the attribute repository; case-sensitivity mismatch in attribute names; user record simply lacks the attribute; principalAttributeNames left over from a copied config for a different directory schema.","solutions":["Check cas.authn.attributeRepository.core.principalAttributeNames and verify each name exists exactly (case included) in the attributes returned by your attribute repository","Enable debug logging for org.apereo.cas.authentication.principal.resolvers to inspect the actual retrieved attribute keys","Correct the LDAP/attribute-repository filter or returned attributes so the desired attribute is fetched","Remove the principalAttributeNames setting if falling back to the username is actually desired"],"exampleFix":"// before\ncas.authn.attributeRepository.core.principalAttributeNames=mail\n// (directory returns 'emailAddress')\n// after\ncas.authn.attributeRepository.core.principalAttributeNames=emailAddress","handlingStrategy":"validation","validationCode":"// before CAS startup, assert configured principal attributes exist in the repository output\nSet<String> attrs = principalAttributes.keySet();\nList<String> configured = List.of(\"mail\"); // cas.authn...principalAttributeNames\nif (configured.stream().noneMatch(attrs::contains)) {\n    throw new IllegalStateException(\"None of \" + configured + \" present in \" + attrs);\n}","typeGuard":"boolean hasPrincipalAttribute(Map<String,Object> attrs, List<String> names) {\n    return names != null && names.stream().anyMatch(n -> attrs.containsKey(n.trim()));\n}","tryCatchPattern":null,"preventionTips":["Keep principalAttributeNames in sync with the directory schema and attribute release policy","Enable DEBUG logging for the principal resolver during environment rollouts","Use an integration test that resolves a sample user through the attribute repository"],"tags":["principal-resolution","attribute-repository","configuration","ldap"],"backgroundTag":"invalid-config-value","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"}