apereo/cas · warning
Located claim [ ] mapped to attribute [ ], yet resolved…
Error message
Located claim [{}] mapped to attribute [{}], yet resolved attributes [{}] do not contain attribute [{}] What it means
In BaseOidcScopeAttributeReleasePolicy.mapClaimToAttribute, a claim is mapped to a source attribute name via the claims-to-attributes mapping, but the resolved principal attributes do not contain an attribute under that mapped name. CAS logs a warning and continues without releasing a value for that claim, so the resulting ID/access token will omit the claim even though the scope requested it.
Solutions
- Fix the claim mapping in the OIDC registered service so each claim maps to the actual attribute name present on the principal.
- Ensure the attribute source (e.g. LDAP attribute 'mail') is released/fetched for the user and named consistently.
- Alternatively remove the mapped attribute name so the claim is looked up directly from resolved attributes by claim name.
Example fix
// before (service json)
"oidcClaims": { "@class": "java.util.TreeMap", "email": "mail" }
// after - map to the attribute actually resolved, or drop the mapping
"oidcClaims": { "@class": "java.util.TreeMap", "email": "email" } Defensive patterns
Strategy: validation
Validate before calling
// Before relying on a mapped claim, check the attribute exists on the principal
Map<String, List<Object>> resolved = principal.getAttributes();
if (!resolved.containsKey(mappedAttr)) {
LOGGER.warn("Mapped attribute {} missing for principal {}", mappedAttr, principal.getId());
} Type guard
boolean hasMappedAttribute(Principal p, String mappedAttr) {
return p != null && p.getAttributes() != null && p.getAttributes().containsKey(mappedAttr);
} Prevention
- Keep the claims->attribute mapping in service JSON synchronized with actual attribute source names
- Audit released attributes per user after LDAP/source changes
- Prefer mapping claims to the same-named attribute to avoid indirection
When it happens
Trigger: Calling getAttributesInternal (during token/ID token generation for an OIDC service) when the service's oidcClaims mapping maps a claim (e.g. 'email') to an attribute name (e.g. 'mail') that does not exist in the principal's resolved attribute set.
Common situations: Mismatch between the LDAP/SAML attribute names released by the attribute repository and the attribute names configured in the OIDC service's claim mapping; user records missing the attribute; typo in the mapped attribute name in the service JSON.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Missing required principal attribute for claim
- Service definition [ ] does not request a pairwise subject…
- JWKS cannot contain expressions
- Unable to use 'none' as introspection signing algorithm
- Unable to use 'none' as introspection encryption algorithm
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/94007f5874b686c2.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-oidc-core/src/main/java/org/apereo/cas/oidc/claims/BaseOidcScopeAttributeReleasePolicy.java:107
LOGGER.debug("Mapped attribute [{}] to [{}] from script", claim, result);
return Pair.of(claim, result);
}
}
if (resolvedAttributes.containsKey(mappedAttr)) {
val value = resolvedAttributes.get(mappedAttr);
LOGGER.debug("Found mapped attribute [{}] with value [{}] for claim [{}]", mappedAttr, value, claim);
return Pair.of(claim, value);
}
if (resolvedAttributes.containsKey(claim)) {
val value = resolvedAttributes.get(claim);
LOGGER.debug("CAS is unable to find the attribute [{}] that is mapped to claim [{}]. "
+ "However, since resolved attributes [{}] already contain this claim, "
+ "CAS will use [{}] with value(s) [{}]",
mappedAttr, claim, resolvedAttributes, claim, value);
return Pair.of(claim, value);
}
LOGGER.warn("Located claim [{}] mapped to attribute [{}], yet "
+ "resolved attributes [{}] do not contain attribute [{}]",
claim, mappedAttr, resolvedAttributes, mappedAttr);
}
val value = resolvedAttributes.get(claim);
LOGGER.debug("No mapped attribute is defined for claim [{}]; Used [{}] to locate value [{}]", claim, claim, value);
return Pair.of(claim, value);
}
@Override
public Map<String, List<Object>> getAttributesInternal(final RegisteredServiceAttributeReleasePolicyContext context,
final Map<String, List<Object>> attributes) {
val resolvedAttributes = new TreeMap<String, List<Object>>(String.CASE_INSENSITIVE_ORDER);
resolvedAttributes.putAll(attributes);
val attributesToRelease = new HashMap<String, List<Object>>(attributes.size());
LOGGER.debug("Attempting to map and filter claims based on resolved attributes [{}]", resolvedAttributes);
View on GitHub (pinned to e7288fc434)