apereo/cas · warning
Cannot find entity [ ] in metadata provider for criteria [ ]
Error message
Cannot find entity [{}] in metadata provider for criteria [{}] What it means
During SAML IdP metadata resolution, the chaining metadata resolver was queried with a criteria set for a specific entityID, but resolveSingle() returned null — no EntityDescriptor for that entity exists in the configured metadata provider(s). The adaptor logs a warning and returns Optional.empty() rather than throwing, because the metadata aggregate loaded fine but simply does not contain that SP's entity ID.
Solutions
- Compare the entityID on the CAS registered service with the entityID in the metadata document at the configured metadataLocation (grep for <EntityDescriptor entityID=...>).
- Re-download/refresh the metadata source (URL may serve an outdated aggregate) and clear the metadata resolver cache so CAS reloads it.
- Verify the metadataLocation (file/URL/HTTP/Classpath resource) on the SamlRegisteredService points to the intended provider.
- If the SP intentionally changed entity IDs, update the SP metadata and the CAS service entityID together.
- Enable debug logging for org.apereo.cas.support.saml to see which metadata chain was resolved and confirm the expected entity is absent.
Example fix
// before (service config) // entityId: https://sp.example.org/sso/old // after // entityId: https://sp.example.org/saml/sp (matches <EntityDescriptor entityID="https://sp.example.org/saml/sp"> in metadata)
Defensive patterns
Strategy: validation
Validate before calling
// Before registering the service, verify the entity exists in the metadata source
var resolver = SamlMetadataResolverUtils.getMetadataResolverForRegisteredService(casProperties, samlIdPMetadataResolver, registeredService);
var found = resolver.resolveSingle(new CriteriaSet(new EntityIdCriterion(service.getEntityId())));
if (found == null) {
throw new IllegalStateException("Metadata at " + service.getMetadataLocation()
+ " does not contain entity " + service.getEntityId());
} Type guard
boolean metadataContainsEntity(EntityDescriptor descriptor, String entityID) {
return descriptor != null && entityID != null && entityID.equals(descriptor.getEntityID());
} Try / catch
return metadataResolver.get(service, entityID)
.map(adaptor -> process(adaptor))
.orElseGet(() -> {
log.warn("No metadata for entity {} — check entityID and metadataLocation", entityID);
return fallbackResponse();
}); Prevention
- Always copy the entityID verbatim from the SP metadata XML into the CAS service definition.
- Pin the metadata source to the SP's published metadata URL so it stays in sync.
- Validate metadata with an XML signature/XMLOnline validator before registering.
- Grep the metadata file for the entityID as a quick sanity check during onboarding.
When it happens
Trigger: Calling SamlRegisteredServiceMetadataAdaptor.get(entityID, ...) (via SamlRegisteredServiceCachingMetadataResolver.get) where the criteria set (entity ID, RolesDescriptor, SPSSODescriptor) matches no entity in the metadata loaded from registeredService.getMetadataLocation().
Common situations: Wrong entityID configured on the CAS SAML service vs. what the SP published in its metadata; stale/aggregate metadata file or URL that no longer contains the SP; typo or case mismatch in entityID; metadata location points to an aggregate missing this SP; SP changed its entityID after a software upgrade.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- Could not locate metadata for
- No assertion consumer service could be found for entity
- Endpoint for is not available or does not define a binding…
- Endpoint for does not define a binding or location for…
- Metadata directory location cannot be located/created
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/17fbdf4c8e12d77e.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-saml-idp-core/src/main/java/org/apereo/cas/support/saml/services/idp/metadata/SamlRegisteredServiceMetadataAdaptor.java:108
final SamlRegisteredServiceCachingMetadataResolver resolver,
final SamlRegisteredService registeredService,
final String entityID,
final CriteriaSet criteriaSet) {
try {
LOGGER.trace("Adapting SAML metadata for CAS service [{}] issued by [{}]", registeredService.getName(), entityID);
criteriaSet.add(new EntityIdCriterion(entityID), true);
LOGGER.debug("Locating metadata for entityID [{}] by attempting to run through the metadata chain...", entityID);
val cachedResult = Objects.requireNonNull(resolver.resolve(registeredService, criteriaSet),
() -> "Metadata resolution resulted in a null metadata resolver entry for entity id %s".formatted(entityID));
Assert.isTrue(cachedResult.isResolved(), "Metadata resolution resulted in an unknown metadata resolver entry for entity id %s".formatted(entityID));
val cachedMetadataResolver = cachedResult.getMetadataResolver();
LOGGER.debug("Resolved metadata chain from [{}] using [{}]. Filtering the chain by entity ID [{}]",
registeredService.getMetadataLocation(), cachedMetadataResolver.getId(), entityID);
val entityDescriptor = cachedMetadataResolver.resolveSingle(criteriaSet);
if (entityDescriptor == null) {
LOGGER.warn("Cannot find entity [{}] in metadata provider for criteria [{}]", entityID, criteriaSet);
return Optional.empty();
}
LOGGER.trace("Located entity descriptor in metadata for [{}]", entityID);
if (entityDescriptor.getValidUntil() != null) {
val expired = entityDescriptor.getValidUntil()
.isBefore(ZonedDateTime.now(ZoneOffset.UTC).toInstant());
if (expired) {
LOGGER.warn("Entity descriptor in the metadata has expired at [{}]", entityDescriptor.getValidUntil());
return Optional.empty();
}
}
return getAdaptor(entityID, cachedMetadataResolver, entityDescriptor);
} catch (final Exception e) {
LoggingUtils.error(LOGGER, e);
}
return Optional.empty();
}View on GitHub (pinned to e7288fc434)