apereo/cas · error · SamlException
Unable to get entity from MDQ server and a backup file does…
Error message
Unable to get entity from MDQ server and a backup file does not exist.
What it means
Thrown by the MDQ (Metadata Query Protocol) resolver when the HTTP response from the MDQ server is not a 2xx success AND no backup metadata file exists on disk for the entity. The resolver normally caches fetched metadata to a backup file so it can serve it during outages; without either a live response or a cached copy, metadata resolution cannot proceed.
Solutions
- Verify the MDQ server URL and that it responds 200 for the entityID (curl the query URL).
- Check network/proxy connectivity from the CAS server to the MDQ server.
- If metadata is available from a prior fetch, restore the backup file to the configured location.
- Fix the entityID configured on the SAML registered service so MDQ can find the entity.
- Configure a reachable MDQ endpoint or switch the service to static metadata.
Example fix
// before cas.authn.saml.idp.metadata.query-protocol.url=https://wrong-mdq.example.org/idp // after cas.authn.saml.idp.metadata.query-protocol.url=https://mdq.example.org/mdq
Defensive patterns
Strategy: fallback
Validate before calling
val queryUrl = mdqBaseUrl + "/entities/" + EncodingUtils.urlEncode(entityId);
if (!Files.exists(backupPath)) {
try (var conn = new URL(queryUrl).openConnection()) { conn.connect(); }
} Type guard
boolean hasBackup(File f) { return f != null && Files.exists(f.toPath()); } Try / catch
try {
return resolver.resolve(criteriaSet);
} catch (SamlException e) {
LOGGER.warn("MDQ fetch failed, trying backup metadata", e);
return loadFromStaticBackup(criteriaSet);
} Prevention
- Pre-seed the MDQ backup directory with known IdP metadata before first deployment.
- Monitor MDQ server availability and alert on non-2xx responses.
- Validate the MDQ URL configuration in staging before production.
- Mount backup metadata on persistent storage in containers.
When it happens
Trigger: Calling resolveFromMetadataQueryProtocolServer (via getMetadataResolverFromResponse) when the MDQ server returns a non-2xx status (404 for unknown entityID, 500, timeout at gateway) and backupFile does not exist on disk (first fetch never succeeded or the file was deleted).
Common situations: MDQ server down or misconfigured URL in cas.authn.saml.idp.metadata.query-protocol.*; wrong entityID requested (404); firewall/proxy blocking outbound HTTP; first-time setup with no cached backup; backup directory wiped or not writable in a container restart.
Related errors
- Unable to determine entity id to fetch metadata via MDQ 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/e30ee616f95cb936.
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/resolver/MetadataQueryProtocolMetadataResolver.java:65
public boolean supports(final SamlRegisteredService service) {
val locations = org.springframework.util.StringUtils.commaDelimitedListToSet(
SpringExpressionLanguageValueResolver.getInstance().resolve(service.getMetadataLocation())
);
return locations.stream().anyMatch(SamlUtils::isDynamicMetadataQueryConfigured);
}
@Override
protected boolean shouldHttpResponseStatusBeProcessed(final HttpStatus status) {
return true;
}
@Override
protected AbstractMetadataResolver getMetadataResolverFromResponse(final HttpResponse response, final File backupFile) throws Exception {
if (!HttpStatus.valueOf(response.getCode()).is2xxSuccessful()) {
if (Files.exists(backupFile.toPath())) {
return new InMemoryResourceMetadataResolver(backupFile, this.configBean);
}
throw new SamlException("Unable to get entity from MDQ server and a backup file does not exist.");
}
val entity = ((HttpEntityContainer) response).getEntity();
val result = IOUtils.toString(entity.getContent(), StandardCharsets.UTF_8);
val path = backupFile.toPath();
LOGGER.trace("Writing metadata to file at [{}]", path);
try (val output = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) {
IOUtils.write(result, output);
output.flush();
StreamSupport.stream(path.getFileSystem().getFileStores().spliterator(), false)
.filter(store -> store.supportsFileAttributeView(UserDefinedFileAttributeView.class))
.forEach(store -> setFileAttribute(response, backupFile));
}
EntityUtils.consume(entity);
return new InMemoryResourceMetadataResolver(backupFile, configBean);
}
@Override
protected HttpResponse fetchMetadata(final SamlRegisteredService service,View on GitHub (pinned to e7288fc434)