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

  1. Verify the SamlRegisteredService's metadataLocation (URL/file/MDQ) is correct, reachable from the CAS server, and returns valid SAML metadata.
  2. Confirm the issuer entityID in the AuthnRequest exactly matches an EntityDescriptor entityID inside that metadata (check for typos and case).
  3. Check the metadata cache: restart or force metadata refresh if validUntil/backoff caused stale or skipped refreshes; look for refresh errors in logs.
  4. If using an aggregate, validate it with an XML signature/validity check; expired aggregates are dropped by the resolver.
  5. 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

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


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)