apereo/cas · warning
[ ] does not match the recommended pattern [ ]. While CAS…
Error message
[{}] does not match the recommended pattern [{}]. While CAS tries to be forgiving as much as possible, it's recommended that you rename the file to match the requested pattern to avoid issues with duplicate service loading. Future CAS versions may try to strictly force the naming syntax, refusing to load the file. What it means
Service definition files must be named '<id>-<something>.<ext>' matching the registry's serviceFileNamePattern (id-based, e.g. 10000001-MyApp.json). If load(File) sees a file with a valid extension but a non-conforming name, CAS logs this warning and still loads it, but warns that duplicates and future strict enforcement may cause problems.
Solutions
- Rename the file to match the pattern '<numericId>-<serviceName>.json' (e.g. 10000001-MyApp.json).
- Ensure the numeric id in the filename matches the id inside the JSON to avoid duplicate-loading issues.
- Redeploy/mount the corrected files and reload the registry; confirm the warning disappears.
Example fix
// before mv myapp.json /etc/cas/config/services/ // after mv myapp.json /etc/cas/config/services/10000001-MyApp.json
Defensive patterns
Strategy: validation
Validate before calling
// Validate filename before dropping into services dir
String name = file.getName();
if (!name.matches("\\d+-[\\w.-]+\\.(json|yaml|yml)")) {
throw new IllegalArgumentException("Rename to <numericId>-<serviceName>.json: " + name);
} Prevention
- Follow the '<id>-<name>.json' naming convention for every service file.
- Keep the filename id identical to the JSON 'id' field.
- Add a lint step in your deployment pipeline that validates service file names.
When it happens
Trigger: Placing a file like 'myapp.json' or '10000001.json' (no dash-separated unique suffix) into the services directory, then having CAS scan/load it; RegexUtils.matches(serviceFileNamePattern, fileName) fails.
Common situations: Renaming files manually without following the CAS convention; migrating service definitions from another system; copy-paste of service files with arbitrary names.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- Provided file [ ] does not match the recommended service…
- The service definition file could not be saved at
- Unauthorized
- Service is not found or is disabled in the service registry.
- Registered service template definition
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/a714c00de3590b01.
Report an issue: GitHub.
Appendix: source
Thrown at core/cas-server-core-services-registry/src/main/java/org/apereo/cas/services/resource/AbstractResourceBasedServiceRegistry.java:288
if (!file.exists()) {
LOGGER.warn("[{}] is not found at the path specified", fileName);
return new ArrayList<>();
}
if (file.length() == 0) {
LOGGER.debug("[{}] appears to be empty so no service definition will be loaded", fileName);
return new ArrayList<>();
}
if (!fileName.isEmpty() && fileName.charAt(0) == '.') {
LOGGER.debug("[{}] starts with ., ignoring", fileName);
return new ArrayList<>();
}
if (Arrays.stream(getExtensions()).noneMatch(fileName::endsWith)) {
LOGGER.debug("[{}] doesn't end with valid extension, ignoring", fileName);
return new ArrayList<>();
}
if (!RegexUtils.matches(this.serviceFileNamePattern, fileName)) {
LOGGER.warn("[{}] does not match the recommended pattern [{}]. "
+ "While CAS tries to be forgiving as much as possible, it's recommended "
+ "that you rename the file to match the requested pattern to avoid issues with duplicate service loading. "
+ "Future CAS versions may try to strictly force the naming syntax, refusing to load the file.",
fileName, this.serviceFileNamePattern.pattern());
}
LOGGER.debug("Attempting to read and parse [{}]", file.getAbsoluteFile());
try (val in = Files.newBufferedReader(file.toPath())) {
return registeredServiceSerializers
.stream()
.filter(serializer -> serializer.supports(file))
.map(serializer -> serializer.load(in))
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.filter(service -> StringUtils.isNotBlank(service.getServiceId()) && StringUtils.isNotBlank(service.getName()))
.map(this::invokeServiceRegistryListenerPostLoad)
.filter(Objects::nonNull)
.collect(Collectors.toList());View on GitHub (pinned to e7288fc434)