apereo/cas · error · IllegalArgumentException
subordinate directory
Error message
subordinate directory [%s] does not exist
What it means
During repository initialization, loadSubordinates() validates the configured subordinate directory before scanning it for OidcFederationSubordinate JSON files. If the path is non-blank but Files.exists() reports no such path, it throws this IllegalArgumentException to fail fast with the offending path in the message.
Solutions
- Create the directory at the configured path: mkdir -p <subordinateDirectory> and place subordinate JSON files in it
- Correct the cas.oidc.federation subordinate-directory property to an existing absolute path
- In containers, mount the directory into the container at the exact configured path and restart CAS
Example fix
// before cas.oidc.federation.subordinate-directory=/etc/cas/oidc/subordinates // directory missing -> error // after # on host mkdir -p /etc/cas/oidc/subordinates # place *.json subordinate entity files there, then restart CAS
Defensive patterns
Strategy: validation
Validate before calling
val dir = Paths.get(subordinateDirectory);
if (StringUtils.isBlank(subordinateDirectory) || !Files.exists(dir) || !Files.isDirectory(dir)) {
throw new IllegalStateException("Subordinate directory not usable: " + subordinateDirectory);
} Try / catch
try {
repository = new OidcFederationSubordinateRepository(oidcProperties, ...);
} catch (IllegalArgumentException e) {
LOGGER.error("Subordinate dir missing: {}", e.getMessage());
} Prevention
- Create the directory before CAS startup and add a deployment healthcheck for it
- Use absolute paths in configuration
- In containers, verify volume mounts with an init/entrypoint check
When it happens
Trigger: CAS starts with cas.oidc.federation.subordinate-directory (or equivalent bean argument) pointing to a path that does not exist on disk, e.g. a typo, an unmounted volume, or a container path not mounted into the CAS server.
Common situations: Docker/Kubernetes deployments where the subordinate JSON directory is not mounted or mounted at a different path; developer copied a config from another host; directory created after CAS startup with no restart; relative path resolved against an unexpected working directory.
Related errors
- subordinate directory
- Unable to build a MongoDb client without any hosts/servers…
- Cannot read/load from subordinate directory
- Invalid unique index: must be >= 0 and < 256
- Unable to create folder
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/16d70f73484c029f.
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:42
@Slf4j
public class OidcFederationSubordinateRepository {
private static final ObjectMapper MAPPER = JacksonObjectMapperFactory.builder()
.defaultTypingEnabled(false).build().toObjectMapper();
@Getter
private final Map<String, OidcFederationSubordinate> subordinates = new HashMap<>();
public OidcFederationSubordinateRepository(final OidcProperties oidcProperties) {
loadSubordinates(oidcProperties.getFederation().getSubordinateDirectory());
}
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)