apereo/cas · critical · IllegalArgumentException

Metadata directory location cannot be located/created

Error message

Metadata directory location  cannot be located/created

What it means

GitSamlIdPMetadataLocator.getMetadataDirectory() computes the per-service metadata directory under the git repository working directory. When no registered service is given (default metadata path) and the directory does not exist yet, it attempts mkdir(); on failure it throws IllegalArgumentException that the metadata directory cannot be located or created.

Solutions

  1. Ensure the git repository directory (cas.authn.samlIdp.metadata.git.repository-directory) exists and is writable by the CAS process user.
  2. Pre-create the expected subdirectory path, including parents (mkdir -p).
  3. Verify the repository was cloned successfully and the working tree is present (not a bare repo path).
  4. Check that nothing at the target path is a regular file blocking directory creation.

Example fix

// before
cas.authn.samlIdp.metadata.git.repository-directory=/var/lib/cas/saml-git   // not writable

// after
sudo mkdir -p /var/lib/cas/saml-git && sudo chown -R cas:cas /var/lib/cas/saml-git
cas.authn.samlIdp.metadata.git.repository-directory=/var/lib/cas/saml-git
Defensive patterns

Strategy: validation

Validate before calling

// before using the git locator
File repo = new File(repositoryDirectory);
if (!repo.isDirectory() || !repo.canWrite())
    throw new IllegalStateException("Git metadata repo missing or unwritable: " + repo);

Try / catch

try {
    File dir = locator.getMetadataDirectory(Optional.empty());
} catch (IllegalArgumentException e) {
    logger.error("Metadata dir problem: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Called by defaultMetadataDirectory()/directory() with registeredService empty; the computed path (repository directory + appliesTo path) does not exist and File.mkdir() returns false (missing parents, permissions, or path is a file).

Common situations: Git metadata repository cloned into a read-only location; parent directories for the service path don't exist; CAS runs as a user that can't write the repository working dir; git repo directory configured incorrectly.

Understand the failure class

Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.

Related errors


AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08). Data as JSON: /api/errors/d1163e7c0b4149dc. Report an issue: GitHub.

Appendix: source

Thrown at support/cas-server-support-saml-idp-metadata-git/src/main/java/org/apereo/cas/support/saml/idp/metadata/GitSamlIdPMetadataLocator.java:79

            .encryptionCertificate(readFromFile(encryptionCert))
            .encryptionKey(readFromFile(encryptionKey))
            .signingCertificate(readFromFile(signingCert))
            .signingKey(readFromFile(signingKey))
            .metadata(readFromFile(metadataFile))
            .build();
    }

    @Override
    protected Resource getMetadataArtifact(final Optional<SamlRegisteredService> registeredService, final String artifactName) {
        val file = getMetadataArtifactFile(registeredService, artifactName);
        return new FileSystemResource(file);
    }

    private File getMetadataDirectory(final Optional<SamlRegisteredService> registeredService) {
        val path = getAppliesToFor(registeredService);
        val directory = new File(gitRepository.getRepositoryDirectory(), path);
        if (!directory.exists() && registeredService.isEmpty() && !directory.mkdir()) {
            throw new IllegalArgumentException("Metadata directory location " + directory + " cannot be located/created");
        }
        return directory;
    }

    private File getMetadataArtifactFile(final Optional<SamlRegisteredService> registeredService,
                                         final String fileName) {
        val defaultMetadataDirectory = getMetadataDirectory(Optional.empty());
        val directory = getMetadataDirectory(registeredService);
        val file = new File(directory, fileName);
        if (file.exists() && file.canRead() && file.length() > 0) {
            return file;
        }
        return new File(defaultMetadataDirectory, fileName);
    }

    private static String readFromFile(final File file) throws IOException {
        return file.exists() && file.canRead() && file.length() > 0
            ? FileUtils.readFileToString(file, StandardCharsets.UTF_8)

View on GitHub (pinned to e7288fc434)