apereo/cas · warning
Attribute repository caching is disabled
Error message
Attribute repository caching is disabled
What it means
The cachingAttributeRepository bean method builds the Caffeine-backed CachingPersonAttributeDaoImpl only when a positive expiration time is configured. When cas.authn.attributeRepository.core.expirationTime is <= 0, caching is skipped entirely and the raw aggregating attribute repository is returned, with this warn explaining why.
Solutions
- Set cas.authn.attributeRepository.core.expirationTime to a positive duration (e.g. PT30M or seconds value)
- Set expirationTime to 0 intentionally only in dev, and silence/expect the warn
- Verify the property is read from the correct config source and not overridden by an environment variable
- If no caching is desired, leave as-is but rely on the underlying repository's own caching
Example fix
# before cas.authn.attributeRepository.core.expirationTime=0 # after cas.authn.attributeRepository.core.expirationTime=PT2H
Defensive patterns
Strategy: validation
Validate before calling
long expiration = casProperties.getAuthn().getAttributeRepository().getCore().getExpirationTime();
if (expiration <= 0) {
log.warn("Attribute repository caching disabled (expirationTime={})", expiration);
} Prevention
- Set cas.authn.attributeRepository.core.expirationTime explicitly in every environment
- Watch for this warn at startup as the signal that caching silently skipped
- Keep expiration settings in the shared CAS properties template, not per-environment ad-hoc files
When it happens
Trigger: cachingAttributeRepository bean is created while cas.authn.attributeRepository.core.expirationTime is 0 or negative (or unset and defaulting to 0).
Common situations: Expiration property never set in cas.properties/application.yml; expiration deliberately set to 0 for development to always see fresh attribute lookups; property typo'd so the default of 0 applies; config migrated from a version with a different default.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- Principal resolution is set to resolve users via…
- No user can be accepted because none is defined
- Not all requested multifactor providers could be found…
- Cookie name is undefined
- List of candidate multifactor authentication providers is…
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/26109e4f175ac385.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-person-directory/src/main/java/org/apereo/cas/config/CasPersonDirectoryConfiguration.java:184
@ConditionalOnMissingBean(name = AttributeRepositoryResolver.BEAN_NAME)
public AttributeRepositoryResolver attributeRepositoryResolver(
@Qualifier(TenantExtractor.BEAN_NAME)
final TenantExtractor tenantExtractor,
final CasConfigurationProperties casProperties,
@Qualifier(ServicesManager.BEAN_NAME) final ServicesManager servicesManager) {
return new DefaultAttributeRepositoryResolver(servicesManager, tenantExtractor, casProperties);
}
@Bean(name = {"cachingAttributeRepository", PrincipalResolver.BEAN_NAME_ATTRIBUTE_REPOSITORY})
@ConditionalOnMissingBean(name = {"cachingAttributeRepository", PrincipalResolver.BEAN_NAME_ATTRIBUTE_REPOSITORY})
@RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
public PersonAttributeDao cachingAttributeRepository(
final CasConfigurationProperties casProperties,
@Qualifier("aggregatingAttributeRepository")
final PersonAttributeDao aggregatingAttributeRepository) {
val props = casProperties.getAuthn().getAttributeRepository().getCore();
if (props.getExpirationTime() <= 0) {
LOGGER.warn("Attribute repository caching is disabled");
return aggregatingAttributeRepository;
}
val impl = new CachingPersonAttributeDaoImpl();
impl.setCacheNullResults(false);
val userinfoCache = Caffeine.newBuilder()
.maximumSize(props.getMaximumCacheSize())
.expireAfterWrite(props.getExpirationTime(), TimeUnit.valueOf(props.getExpirationTimeUnit().toUpperCase(Locale.ENGLISH)))
.build();
impl.setUserInfoCache((Map) userinfoCache.asMap());
impl.setCachedPersonAttributesDao(aggregatingAttributeRepository);
LOGGER.trace("Configured cache expiration policy for attribute sources to be [{}] minute(s)", props.getExpirationTime());
return impl;
}
@Bean
@RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
@ConditionalOnMissingBean(name = "attributeRepositoryAttributeMerger")View on GitHub (pinned to e7288fc434)