{"record":{"id":"2e57b2f73da41541","repo":"apereo/cas","slug":"script-cache-manager-unavailable-to-handle-ldap-fi","errorCode":null,"errorMessage":"Script cache manager unavailable to handle LDAP filter","messagePattern":"Script cache manager unavailable to handle LDAP filter","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"support/cas-server-support-ldap-core/src/main/java/org/apereo/cas/util/LdapUtils.java","lineNumber":379,"sourceCode":"                                val scriptFactory = ExecutableCompiledScriptFactory.getExecutableCompiledScriptFactory();\n                                script = scriptFactory.fromResource(resource);\n                                cacheMgr.put(cacheKey, script);\n                                LOGGER.trace(\"Cached groovy script [{}] for key [{}]\", script, cacheKey);\n                            }\n                            if (script != null) {\n                                val parameters = IntStream.range(0, values.size())\n                                    .boxed()\n                                    .collect(Collectors.toMap(paramName::get, values::get, (a, b) -> b, LinkedHashMap::new));\n                                val args = CollectionUtils.<String, Object>wrap(\"filter\", filter,\n                                    \"parameters\", parameters,\n                                    \"applicationContext\", ApplicationContextProvider.getApplicationContext(),\n                                    \"logger\", LOGGER);\n                                script.setBinding(args);\n                                script.execute(args.values().toArray(), FilterTemplate.class);\n                            }\n                        }),\n                    () -> {\n                        throw new RuntimeException(\"Script cache manager unavailable to handle LDAP filter\");\n                    });\n        } else {\n            filter.setFilter(filterQuery);\n            if (values != null && !values.isEmpty()) {\n                IntStream.range(0, values.size()).forEach(i -> {\n                    val value = values.get(i);\n                    if (filter.getFilter().contains(\"{\" + i + '}')) {\n                        filter.setParameter(i, value);\n                    }\n                    val name = paramName.get(i);\n                    if (filter.getFilter().contains('{' + name + '}')) {\n                        filter.setParameter(name, value);\n                    }\n                });\n            }\n        }\n\n        LOGGER.debug(\"Constructed LDAP search filter [{}]\", filter.format());","sourceCodeStart":361,"sourceCodeEnd":397,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-ldap-core/src/main/java/org/apereo/cas/util/LdapUtils.java#L361-L397","documentation":"LdapUtils.newLdaptiveSearchFilter supports LDAP filters defined as inline Groovy scripts; when the filter is a script, it requires a ScriptCacheManager to compile/cache it. If no script cache manager was provided (null), it fails fast with this RuntimeException rather than executing the script unfiltered.","triggerScenarios":"Calling newLdaptiveSearchFilter(...) with a filter query that contains a Groovy script (scripted filter syntax) while passing null for the ScriptCacheManager argument.","commonSituations":"Using a scripted LDAP filter (e.g. with cas.authn.ldap[x].search-filter written as a Groovy script) but the calling configuration class was constructed without a scriptCacheManager bean; upgrading CAS and adding script-based filters without the script support module/wiring.","solutions":["Ensure the calling component passes its configured ScriptCacheManager into newLdaptiveSearchFilter","Check that the relevant CAS auto-configuration wires the script cache manager bean for your LDAP settings","Rewrite the search filter as a static/template filter (non-Groovy) if scripting is not needed","Verify the Groovy/scripting module is on the classpath and the filter syntax really requires a script"],"exampleFix":"// before: scripted filter without cache manager\n// search-filter=groovy{return 'uid=' + user}\n// and newLdaptiveSearchFilter(query, null, ...)\n// after: pass the manager\nnewLdaptiveSearchFilter(query, scriptCacheManager, params);\n// or use a static filter\n// search-filter=(uid={user})","handlingStrategy":"validation","validationCode":"if (filterQuery != null && filterQuery.contains(\"groovy:\")) {\n    Objects.requireNonNull(scriptCacheManager, \"Scripted LDAP filters require a ScriptCacheManager\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    Filter f = LdapUtils.newLdaptiveSearchFilter(query, scriptCacheManager, params);\n} catch (RuntimeException e) {\n    if (\"Script cache manager unavailable to handle LDAP filter\".equals(e.getMessage())) {\n        // fall back to a static filter or wire the script cache manager\n    }\n}","preventionTips":["Pass a non-null ScriptCacheManager whenever scripted filters are possible","Avoid Groovy-based LDAP filters unless scripting is genuinely required","Ensure the scripting module is included in the CAS overlay","Review upstream calls to LdapUtils for null cache-manager arguments"],"tags":["ldap","groovy","missing-dependency"],"backgroundTag":"missing-required-argument","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"}