apereo/cas · error · IllegalArgumentException
Cannot read/load from subordinate directory
Error message
Cannot read/load from subordinate directory
What it means
After validating the directory, loadSubordinates() walks it and parses each file with Jackson into OidcFederationSubordinate; any IOException while reading or walking (unreadable file, I/O error mid-walk) is rethrown as IllegalArgumentException with this message and the original cause attached.
Solutions
- Inspect the wrapped cause (getCause()) to identify the failing file, then fix its permissions: chmod/chown so the CAS user can read it
- Remove non-JSON junk (broken symlinks, sockets) from the directory
- Verify the filesystem is accessible from the CAS process (mount health, container volume)
- Note: individual JSON parse failures surface differently (UncheckedIOException via doUnchecked); this message is I/O-level
Example fix
// before ls -l /etc/cas/oidc/subordinates -rw------- root root acme.json # CAS user cannot read // after chown cas:cas /etc/cas/oidc/subordinates/acme.json chmod 640 /etc/cas/oidc/subordinates/acme.json
Defensive patterns
Strategy: try-catch
Validate before calling
try (var s = Files.walk(Paths.get(subordinateDirectory))) {
s.filter(Files::isRegularFile).forEach(p -> {
if (!Files.isReadable(p)) throw new IllegalStateException("Unreadable: " + p);
});
} catch (IOException e) { /* provision error */ } Try / catch
try {
repository = new OidcFederationSubordinateRepository(...);
} catch (IllegalArgumentException e) {
LOGGER.error("Subordinate load I/O failed", e.getCause());
} Prevention
- Run CAS under a user with read access to all subordinate files
- Keep only regular JSON files in the directory
- Monitor filesystem/NFS health in deployment
When it happens
Trigger: A regular file inside the directory cannot be read or a Files.walk()/readValue() I/O error occurs during repository construction at CAS startup.
Common situations: Files owned by another user with no read permission for the CAS process; broken symlink or special file inside the directory; NFS mount dropped mid-startup; truncated/locked file.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- The service definition file could not be saved at
- subordinate directory
- subordinate directory
- Unable to create folder
- Unable to build a MongoDb client without any hosts/servers…
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/18fe21c9bf78fdc8.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-oidc-federation/src/main/java/org/apereo/cas/oidc/federation/subordinate/OidcFederationSubordinateRepository.java:55
protected void loadSubordinates(final String subordinateDirectory) {
if (StringUtils.isNotBlank(subordinateDirectory)) {
LOGGER.debug("Loading subordinates...");
val dir = Paths.get(subordinateDirectory);
if (!Files.exists(dir)) {
throw new IllegalArgumentException("subordinate directory [%s] does not exist".formatted(subordinateDirectory));
}
if (!Files.isDirectory(dir)) {
throw new IllegalArgumentException("subordinate directory [%s] is not a directory".formatted(subordinateDirectory));
}
try (val stream = Files.walk(dir).filter(Files::isRegularFile).filter(Files::isReadable)) {
stream.forEach(path -> FunctionUtils.doUnchecked(_ -> {
val file = path.toFile();
LOGGER.debug("Parsing [{}]...", file);
val subordinate = MAPPER.readValue(file, OidcFederationSubordinate.class);
subordinates.put(subordinate.getEntityId(), subordinate);
}));
} catch (final IOException e) {
throw new IllegalArgumentException("Cannot read/load from subordinate directory", e);
}
LOGGER.info("Loaded [{}] subordinates", subordinates.size());
}
}
}
View on GitHub (pinned to e7288fc434)