{"record":{"id":"aa3426d89e1cbb6f","repo":"apereo/cas","slug":"theme-for-service-cannot-be-located","errorCode":null,"errorMessage":"Theme [{}] for service [{}] cannot be located","messagePattern":"Theme \\[(.+?)\\] for service \\[(.+?)\\] cannot be located","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"support/cas-server-support-themes-core/src/main/java/org/apereo/cas/services/web/RegisteredServiceThemeResolver.java","lineNumber":186,"sourceCode":"\n    protected String resolveThemeForService(final WebBasedRegisteredService registeredService,\n                                            final HttpServletRequest request) {\n        val theme = SpringExpressionLanguageValueResolver.getInstance().resolve(registeredService.getTheme());\n        if (casProperties.getObject().getView().getTemplatePrefixes()\n            .stream()\n            .map(prefix -> Strings.CI.appendIfMissing(prefix, \"/\").concat(theme).concat(\".properties\"))\n            .anyMatch(ResourceUtils::doesResourceExist)) {\n            LOGGER.trace(\"Found custom external theme [{}] for service [{}]\", theme, registeredService.getName());\n            return theme;\n        }\n        val messageSource = new CasThemeResourceBundleMessageSource();\n        messageSource.setBasename(theme);\n        if (messageSource.doGetBundle(theme, request.getLocale()) != null) {\n            LOGGER.trace(\"Found custom theme [{}] for service [{}]\", theme, registeredService.getName());\n            return theme;\n        }\n\n        LOGGER.warn(\"Theme [{}] for service [{}] cannot be located\", theme, registeredService.getName());\n        return null;\n    }\n\n}\n","sourceCodeStart":168,"sourceCodeEnd":191,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-themes-core/src/main/java/org/apereo/cas/services/web/RegisteredServiceThemeResolver.java#L168-L191","documentation":"resolveThemeForService validates the service's configured theme by attempting to load a ResourceBundleMessageSource with the theme name as basename; if doGetBundle returns null the bundle cannot be loaded, so the theme is considered invalid and null is returned (leading to default-theme fallback). This is the concrete check that produces the 'cannot be located' outcome.","triggerScenarios":"registeredService.getTheme() returns a name for which messageSource.doGetBundle(theme, locale) finds no bundle — the theme properties file is absent from the classpath or its basename does not match.","commonSituations":"Theme directory exists in views but theme.properties / messages bundle missing; theme packaged in a module not on the runtime classpath; case-sensitivity mismatch in the theme name on Linux.","solutions":["Create or restore the theme's properties bundle at the expected basename (classpath:/<theme>/theme.properties).","Fix the theme name in the service definition to match the actual bundle basename.","Ensure the theme resource JAR is included in the deployed WAR.","Check filename case matches the theme name (Linux classpath lookups are case-sensitive)."],"exampleFix":"// theme 'mytheme' must ship:\n// src/main/resources/mytheme/theme.properties\nlogintheme.css=/themes/mytheme/css/login.css","handlingStrategy":"validation","validationCode":"// pre-check that the theme basename is loadable\nString theme = registeredService.getTheme();\ntry (var in = getClass().getResourceAsStream(\"/\" + theme + \"/theme.properties\")) {\n    if (in == null) throw new IllegalStateException(\"Theme bundle missing: \" + theme);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Include theme.properties in every custom theme's resources directory.","Use exact-case theme names to avoid Linux classpath case-sensitivity issues.","Verify theme JAR is on the runtime classpath after deployment."],"tags":["themes","message-source","resource-not-found","classpath"],"backgroundTag":"resource-not-found","analyzedSha":"e7288fc434b4f4505b8452e1a57e8fb3111bb863","analyzedAt":"2026-09-08T15:39:16.015Z","contentChangedAt":"2026-09-08T15:39:16.015Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}