{"record":{"id":"d25163e19e4e0c6f","repo":"apereo/cas","slug":"subordinate-directory-s-is-not-a-directory","errorCode":null,"errorMessage":"subordinate directory [%s] is not a directory","messagePattern":"subordinate directory \\[(.+?)\\] is not a directory","errorType":"console","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"support/cas-server-support-oidc-federation/src/main/java/org/apereo/cas/oidc/federation/subordinate/OidcFederationSubordinateRepository.java","lineNumber":45,"sourceCode":"    private static final ObjectMapper MAPPER = JacksonObjectMapperFactory.builder()\n        .defaultTypingEnabled(false).build().toObjectMapper();\n\n    @Getter\n    private final Map<String, OidcFederationSubordinate> subordinates = new HashMap<>();\n\n    public OidcFederationSubordinateRepository(final OidcProperties oidcProperties) {\n        loadSubordinates(oidcProperties.getFederation().getSubordinateDirectory());\n    }\n\n    protected void loadSubordinates(final String subordinateDirectory) {\n        if (StringUtils.isNotBlank(subordinateDirectory)) {\n            LOGGER.debug(\"Loading subordinates...\");\n            val dir = Paths.get(subordinateDirectory);\n            if (!Files.exists(dir)) {\n                throw new IllegalArgumentException(\"subordinate directory [%s] does not exist\".formatted(subordinateDirectory));\n            }\n            if (!Files.isDirectory(dir)) {\n                throw new IllegalArgumentException(\"subordinate directory [%s] is not a directory\".formatted(subordinateDirectory));\n            }\n            try (val stream = Files.walk(dir).filter(Files::isRegularFile).filter(Files::isReadable)) {\n                stream.forEach(path -> FunctionUtils.doUnchecked(_ -> {\n                    val file = path.toFile();\n                    LOGGER.debug(\"Parsing [{}]...\", file);\n                    val subordinate = MAPPER.readValue(file, OidcFederationSubordinate.class);\n                    subordinates.put(subordinate.getEntityId(), subordinate);\n                }));\n            } catch (final IOException e) {\n                throw new IllegalArgumentException(\"Cannot read/load from subordinate directory\", e);\n            }\n            LOGGER.info(\"Loaded [{}] subordinates\", subordinates.size());\n        }\n    }\n}\n","sourceCodeStart":27,"sourceCodeEnd":61,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-oidc-federation/src/main/java/org/apereo/cas/oidc/federation/subordinate/OidcFederationSubordinateRepository.java#L27-L61","documentation":"loadSubordinates() checks Files.isDirectory() after confirming the path exists; if the configured subordinate location resolves to a regular file (or other non-directory), it throws this IllegalArgumentException naming the path.","triggerScenarios":"The subordinate-directory config value points at a file (e.g. a single JSON document or an archive) instead of a directory that Files.walk() can traverse.","commonSituations":"Operator set the property to a JSON file expecting single-entity config; a symlink points at a file; tar extraction replaced the directory with a file.","solutions":["Ensure the configured path is a directory and move the subordinate JSON files into it","Update the config to the directory path, not the individual file path","If a single subordinate is intended, wrap it in a directory containing one JSON file"],"exampleFix":"// before\nsubordinate-directory=/etc/cas/oidc/subordinates/acme.json  # a file\n// after\nsubordinate-directory=/etc/cas/oidc/subordinates  # directory containing acme.json","handlingStrategy":"validation","validationCode":"if (!Files.isDirectory(Paths.get(subordinateDirectory))) {\n    throw new IllegalStateException(\"Path is not a directory: \" + subordinateDirectory);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Point config at directories, never at individual JSON files","Check symlinks resolve to a directory","Script-provision the directory structure in deployment"],"tags":["filesystem","configuration","startup"],"backgroundTag":"path-is-not-a-directory","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"}