apereo/cas · warning
CRL data is not available for
Error message
CRL data is not available for [{}] What it means
Logged in AbstractCRLRevocationChecker.check() when getCRLs(cert) returns null or an empty collection, meaning no CRL could be fetched or computed for the certificate. The checker then delegates to the configured unavailableCRLPolicy (e.g. ALLOW or DENY), so the outcome depends on CAS x509 configuration. It is a warning because it may simply reflect an unreachable CRL distribution point rather than a code bug.
Solutions
- Verify the CRL distribution point URL is reachable from the CAS server: 'curl -v <crlDP-url>'.
- Set cas.authn.x509.crl.* / unavailable-CRL-policy explicitly (allow or deny) so behavior is intentional.
- Configure a fetcher/cache (e.g. ResourceCRLFetcher, CRL distribution point caching) or point CAS at an OCSP responder instead.
- If the certificate legitimately has no CRLDP, switch to OCSP-based checking or disable revocation for that CA.
Example fix
// before (cas.properties) cas.authn.x509.crl.revocation-policy=ALLOW // after cas.authn.x509.crl.revocation-policy=DENY cas.authn.x509.crl.fetcher=resource cas.authn.x509.crl.resource.location=file:/etc/cas/crls/ca.crl
Defensive patterns
Strategy: validation
Validate before calling
String crlDp = ""; // extract from cert CRL distribution points extension
if (crlDp == null || crlDp.isBlank()) {
throw new IllegalStateException("Certificate has no CRL distribution point; enable OCSP or skip revocation");
} Type guard
if (crls == null || crls.isEmpty()) { /* handle unavailable-CRL case explicitly before check() */ } Try / catch
try {
checker.check(cert);
} catch (RevokedCertificateException e) {
throw e;
} catch (GeneralSecurityException e) {
// includes unavailable-CRL outcomes when policy is DENY
LOGGER.warn("Revocation status unavailable for [{}]", CertUtils.toString(cert), e);
} Prevention
- Confirm CRL distribution point URLs are reachable from the CAS server (curl them).
- Explicitly set the unavailable-CRL policy (allow vs deny) rather than relying on defaults.
- Monitor CRL fetch failures with alerts on the distribution point host.
- Configure OCSP as a secondary revocation source when CRLs may be missing.
When it happens
Trigger: X509 credential revocation checking is enabled and the certificate's CRL distribution point URL is unreachable, the CRL fetch returns nothing, or no revocation checker is configured to supply CRL data for the certificate.
Common situations: CRL distribution point host unreachable/offline from the CAS server (firewall, DNS, expired URL); certificate issued without CRLDP extension; x509 revocation checking turned on but no CRL resource configured; caching fetcher returning expired/empty entries.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- Failed to establish a connection ldap and search.
- Unknown CRL reason code.
- CRL data expired on [ ]
- All CRL entries have been revoked. Rejecting the first entry
- Unable to accept certificate
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/32c01ccbebb956a8.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-x509-core/src/main/java/org/apereo/cas/adaptors/x509/authentication/revocation/checker/AbstractCRLRevocationChecker.java:65
* that produces the cert.
* @param unavailableCRLPolicy the unavailable crl policy
* @param expiredCRLPolicy the expired crl policy
*/
protected AbstractCRLRevocationChecker(final boolean checkAll,
final RevocationPolicy<Void> unavailableCRLPolicy,
final RevocationPolicy<X509CRL> expiredCRLPolicy) {
this.checkAll = checkAll;
this.unavailableCRLPolicy = Objects.requireNonNullElseGet(unavailableCRLPolicy, DenyRevocationPolicy::new);
this.expiredCRLPolicy = Objects.requireNonNullElseGet(expiredCRLPolicy, () -> new ThresholdExpiredCRLRevocationPolicy(0));
}
@Override
public void check(@NonNull final X509Certificate cert) throws GeneralSecurityException {
LOGGER.debug("Evaluating certificate revocation status for [{}]", CertUtils.toString(cert));
val crls = getCRLs(cert);
if (crls == null || crls.isEmpty()) {
LOGGER.warn("CRL data is not available for [{}]", CertUtils.toString(cert));
this.unavailableCRLPolicy.apply(null);
return;
}
val expiredCrls = new ArrayList<X509CRL>(crls.size());
crls.stream().filter(CertUtils::isExpired).forEach(crl -> {
LOGGER.warn("CRL data expired on [{}]", crl.getNextUpdate());
expiredCrls.add(crl);
});
if (crls.size() == expiredCrls.size()) {
LOGGER.warn("All CRLs retrieved have expired. Applying CRL expiration policy...");
for (val crl : expiredCrls) {
this.expiredCRLPolicy.apply(crl);
}
} else {
crls.removeAll(expiredCrls);
LOGGER.debug("Valid CRLs [{}] found that are not expired yet", crls);View on GitHub (pinned to e7288fc434)