apereo/cas · error · SamlException
No metadata resolvers could be configured for service with…
Error message
No metadata resolvers could be configured for service with metadata location
What it means
SamlRegisteredServiceMetadataResolverCacheLoader.load() is the LoadingCache loader producing a CachedMetadataResolverResult for a SamlRegisteredServiceCacheKey. If loadMetadataResolvers() returns an empty list — no configured resolver (resource/HTTP/file/db/etc.) applies to or succeeds for the service — it throws SamlException naming the service and its resolved metadata location.
Solutions
- Set a valid metadataLocation on the registered service (e.g. file:/etc/cas/metadata/sp-metadata.xml or https://sp.example.com/metadata) and save it.
- Confirm the scheme of metadataLocation matches an available resolver (HTTP, filesystem, classpath, JDBC, MongoDB, etc.) and the corresponding CAS module is included in the build.
- Check that any SpEL in metadataLocation actually resolves to a non-empty value (log/resolve it manually with SpringExpressionLanguageValueResolver).
- Verify metadata resolution for that location manually (curl/file read) to rule out an empty or unreachable source.
Example fix
// before (service registered without location)
{ "name": "SP", "serviceId": "^https://sp.example.com", "metadataLocation": "" }
// after
{ "name": "SP", "serviceId": "^https://sp.example.com", "metadataLocation": "https://sp.example.com/saml/metadata" } Defensive patterns
Strategy: validation
Validate before calling
// when creating/updating a SAML registered service
String loc = SpringExpressionLanguageValueResolver.getInstance().resolve(service.getMetadataLocation());
if (loc == null || loc.isBlank())
throw new IllegalArgumentException("Service " + service.getName() + " needs a concrete metadataLocation");
if (!(loc.startsWith("http") || loc.startsWith("file") || loc.startsWith("classpath")))
throw new IllegalArgumentException("Unsupported metadataLocation scheme: " + loc); Try / catch
try {
CachedMetadataResolverResult r = cache.get(cacheKey);
} catch (SamlException e) {
logger.error("Service {} metadata misconfigured: {}", service.getName(), e.getMessage());
} Prevention
- Require metadataLocation at service-registration time via management UI/validation.
- Include the CAS module for each metadata scheme you use (file/http/db).
- Test SpEL-based metadata locations resolve to non-empty values in a lower environment.
When it happens
Trigger: load() (public) calls loadMetadataResolvers(cacheKey); the result is empty because the registered service's metadataLocation is blank/unresolvable after Spring EL resolution, or no SamlRegisteredServiceMetadataResolver in the chain matches/supports the location scheme.
Common situations: Registered service created without a metadataLocation; metadataLocation uses an unsupported scheme (e.g. missing http(s)/file prefix) or a SpEL expression that resolves to empty; metadata resource module not on the classpath so no resolver is registered.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- Unable to locate a valid SAML metadata resolver for to…
- Could not decode provided CRL file
- 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/598de86766e38e9e.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-saml-idp-metadata/src/main/java/org/apereo/cas/support/saml/services/idp/metadata/cache/SamlRegisteredServiceMetadataResolverCacheLoader.java:45
* @since 5.0.0
*/
@Slf4j
@RequiredArgsConstructor
public class SamlRegisteredServiceMetadataResolverCacheLoader implements CacheLoader<SamlRegisteredServiceCacheKey, CachedMetadataResolverResult> {
protected final OpenSamlConfigBean configBean;
protected final HttpClient httpClient;
private final SamlRegisteredServiceMetadataResolutionPlan metadataResolutionPlan;
@Override
public CachedMetadataResolverResult load(final SamlRegisteredServiceCacheKey cacheKey) {
val metadataResolvers = loadMetadataResolvers(cacheKey);
if (metadataResolvers.isEmpty()) {
val registeredService = cacheKey.getRegisteredService();
val metadataLocation = SpringExpressionLanguageValueResolver.getInstance().resolve(registeredService.getMetadataLocation());
throw new SamlException("No metadata resolvers could be configured for service " + registeredService.getName()
+ " with metadata location " + metadataLocation);
}
val metadataResolver = initializeChainingMetadataResolver(metadataResolvers);
LOGGER.debug("Metadata resolvers active for this request are [{}]", Objects.requireNonNull(metadataResolvers));
return CachedMetadataResolverResult
.builder()
.cachedInstant(Instant.now(Clock.systemUTC()))
.metadataResolver(metadataResolver)
.build();
}
protected MetadataResolver initializeChainingMetadataResolver(final List<MetadataResolver> metadataResolvers) {
return FunctionUtils.doUnchecked(() -> {
val metadataResolver = new ChainingMetadataResolver();
metadataResolver.setId(ChainingMetadataResolver.class.getCanonicalName());
LOGGER.trace("There are [{}] eligible metadata resolver(s) for this request", metadataResolvers.size());
metadataResolver.setResolvers(metadataResolvers);View on GitHub (pinned to e7288fc434)