apereo/cas · warning
Could not add template prefix
Error message
Could not add template prefix '%s' to resolver: [%s]
What it means
CasThymeleafChainingTemplateViewResolver setup in CasThymeleafAutoConfiguration.iterates over configured view/template paths and, for each prefix, creates a ClassLoaderTemplateResolver or FileTemplateResolver and adds it to the resolver chain. If constructing/configuring the resolver for a prefix throws, the failure is logged with this message and that prefix is skipped; remaining resolvers (theme and default classpath resolvers) still get added.
Solutions
- Fix the offending template prefix entry in configuration (cas.view.template-prefixes or theme view paths).
- Ensure filesystem-based prefixes point to existing, readable directories.
- Use ResourceUtils.CLASSPATH_URL_PREFIX (classpath:) only for resources actually on the classpath.
- Check the chained exception (stack trace logged alongside) for the root resolver error.
Example fix
// before cas.view.template-prefixes[0]=file:/etc/cas/templates/temlates/ // after cas.view.template-prefixes[0]=file:/etc/cas/templates/templates/
Defensive patterns
Strategy: validation
Validate before calling
// validate each configured prefix before startup
casProperties.getView().getTemplatePrefixes().forEach(p -> {
if (p.startsWith("file:") && !java.nio.file.Files.isDirectory(java.nio.file.Path.of(URI.create(p))))
LOGGER.warn("Template prefix is not a directory: {}", p);
}); Prevention
- Validate template prefix paths in deployment scripts.
- Use classpath: prefixes only for resources bundled in the WAR.
- Keep overlay directory structure consistent across environments.
When it happens
Trigger: An exception is thrown while creating/configuring the template resolver for a configured prefix — e.g. the view path is malformed, an invalid URL/resource prefix, or resolver configuration fails for the given thymeleaf properties.
Common situations: Typo or unsupported scheme in a configured template prefix (e.g. bad cas.view.template-prefixes entry); directory expected on disk missing so FileTemplateResolver setup/validation fails; classpath prefix spelled incorrectly.
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
- 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…
- Principal id attribute is not found for [principalAttr]
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/15c0c808f90c1852.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-thymeleaf/src/main/java/org/apereo/cas/config/CasThymeleafAutoConfiguration.java:167
templatePrefixes.forEach(prefix -> {
try {
val prefixPath = prefix.startsWith(ResourceUtils.CLASSPATH_URL_PREFIX)
? prefix
: ResourceUtils.getFile(prefix).getCanonicalPath();
val viewPath = Strings.CI.appendIfMissing(prefixPath, "/");
val theme = prefix.startsWith(ResourceUtils.CLASSPATH_URL_PREFIX)
? new ThemeClassLoaderTemplateResolver(themeResolver)
: new ThemeFileTemplateResolver(casProperties, themeResolver);
configureTemplateViewResolver(theme, thymeleafProperties);
theme.setPrefix(Strings.CI.removeStart(viewPath, ResourceUtils.CLASSPATH_URL_PREFIX) + "themes/%s/");
chain.addResolver(theme);
val template = prefix.startsWith(ResourceUtils.CLASSPATH_URL_PREFIX) ? new ClassLoaderTemplateResolver() : new FileTemplateResolver();
configureTemplateViewResolver(template, thymeleafProperties);
template.setPrefix(Strings.CI.removeStart(viewPath, ResourceUtils.CLASSPATH_URL_PREFIX));
chain.addResolver(template);
} catch (final Exception e) {
LoggingUtils.warn(LOGGER,
String.format("Could not add template prefix '%s' to resolver: [%s]", prefix, e.getMessage()), e);
}
});
chain.addResolver(themeClassLoaderTemplateResolver);
chain.addResolver(classLoaderTemplateResolver);
chain.initialize();
return chain;
}
@Bean
@ConditionalOnMissingBean(name = "themeClassLoaderTemplateResolver")
@RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
public ITemplateResolver themeClassLoaderTemplateResolver(final ThymeleafProperties thymeleafProperties,
@Qualifier("themeResolver") final ThemeResolver themeResolver) {
val themeCp = new ThemeClassLoaderTemplateResolver(themeResolver);
configureTemplateViewResolver(themeCp, thymeleafProperties);
themeCp.setPrefix("templates/%s/");View on GitHub (pinned to e7288fc434)