apereo/cas · error
No metadata could be found for
Error message
No metadata could be found for [{}] What it means
Although the SP was found in the CAS service registry, no SAML metadata adaptor (metadata document) matching the issuer and the incoming AuthnRequest could be resolved from the caching metadata resolver. CAS cannot validate or process the request without the SP's metadata, so it throws UnauthorizedServiceException.denied. This typically means the metadata location configured on the service is wrong, unreachable, or does not contain the entityID.
Solutions
- Verify the SamlRegisteredService's metadataLocation (URL/file/MDQ) is correct, reachable from the CAS server, and returns valid SAML metadata.
- Confirm the issuer entityID in the AuthnRequest exactly matches an EntityDescriptor entityID inside that metadata (check for typos and case).
- Check the metadata cache: restart or force metadata refresh if validUntil/backoff caused stale or skipped refreshes; look for refresh errors in logs.
- If using an aggregate, validate it with an XML signature/validity check; expired aggregates are dropped by the resolver.
- Enable DEBUG logging on org.apereo.cas.support.saml to trace the metadata resolution attempt.
Example fix
// before: metadataLocation points at a dead host "metadataLocation": "https://old-federation.example.org/metadata/sp.xml" // after: correct, reachable metadata containing the SP entityID "metadataLocation": "https://metadata.example.org/sp-metadata.xml"
Defensive patterns
Strategy: validation
Validate before calling
// Pre-check that metadata resolves for the SP
val adaptor = SamlRegisteredServiceMetadataAdaptor.get(resolver, registeredService, authnRequest);
if (adaptor.isEmpty()) throw new IllegalStateException("No SAML metadata for issuer: " + issuer); Type guard
boolean hasMetadata(SamlRegisteredService svc) { return svc != null && StringUtils.isNotBlank(svc.getMetadataLocation()); } Try / catch
try {
verifySamlAuthenticationRequest(...);
} catch (UnauthorizedServiceException e) {
LOGGER.error("Metadata missing for issuer {}", issuer, e);
// surface 'SP metadata not configured' to operators
} Prevention
- Validate metadataLocation URLs from the CAS server's network (curl the URL on the host).
- Set up metadata refresh monitoring; alert on expired validUntil aggregates.
- Ensure SP entityID strings match metadata exactly (copy-paste, not retype).
When it happens
Trigger: verifySamlAuthenticationRequest calls SamlRegisteredServiceMetadataAdaptor.get(resolver, registeredService, authnRequest) and the returned Optional is empty — i.e. metadataCriteria on the service points to an invalid/unreachable URL or file, or the metadata aggregate exists but lacks an EntityDescriptor for the issuer entityID.
Common situations: metadataLocation URL points to a federation aggregate that expired (validUntil passed); typo'd entityID so no EntityDescriptor matches; metadata file not present at the configured path; MDQ/federation server down or returning 404; metadata cached stale after the SP rotated entityID or certificates.
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
- [ ] is not found in the registry or service access is…
- Unable to resolve service provider assertion consumer…
- 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…
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/b3a5d4c01c3b7d42.
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/AbstractSamlIdPProfileHandlerController.java:408
LOGGER.debug("Checking for single sign-on participation for issuer [{}]", issuer);
val ssoAvailable = ssoStrategy.supports(ssoRequest) && ssoStrategy.isParticipating(ssoRequest);
return ssoAvailable ? Optional.of(ticketGrantingTicket) : Optional.empty();
}
protected Pair<SamlRegisteredService, SamlRegisteredServiceMetadataAdaptor> verifySamlAuthenticationRequest(
final Pair<? extends RequestAbstractType, MessageContext> authenticationContext,
final HttpServletRequest request) throws Throwable {
val authnRequest = (AuthnRequest) authenticationContext.getKey();
val issuer = SamlIdPUtils.getIssuerFromSamlObject(authnRequest);
LOGGER.debug("Located issuer [{}] from authentication request", issuer);
val registeredService = verifySamlRegisteredService(issuer, request);
LOGGER.debug("Fetching SAML2 metadata adaptor for [{}]", issuer);
val adaptor = SamlRegisteredServiceMetadataAdaptor.get(
configurationContext.getSamlRegisteredServiceCachingMetadataResolver(), registeredService, authnRequest);
if (adaptor.isEmpty()) {
LOGGER.warn("No metadata could be found for [{}]", issuer);
throw UnauthorizedServiceException.denied("Cannot find metadata linked to %s".formatted(issuer));
}
val facade = adaptor.get();
verifyAuthenticationContextSignature(authenticationContext, request, authnRequest, facade, registeredService);
val binding = determineProfileBinding(authenticationContext, request);
val acs = SamlIdPUtils.determineEndpointForRequest(Pair.of(authnRequest, authenticationContext.getRight()), facade, binding);
LOGGER.debug("Determined SAML2 endpoint for authentication request as [{}]",
StringUtils.defaultIfBlank(acs.getResponseLocation(), acs.getLocation()));
configurationContext.getOpenSamlConfigBean().logObject(authnRequest);
return Pair.of(registeredService, facade);
}
protected void verifyAuthenticationContextSignature(final Pair<? extends SignableSAMLObject, MessageContext> authenticationContext,
final HttpServletRequest request, final RequestAbstractType authnRequest,
final SamlRegisteredServiceMetadataAdaptor adaptor,
final SamlRegisteredService registeredService) throws Throwable {View on GitHub (pinned to e7288fc434)