apereo/cas · warning

Resource [ ] cannot be located

Error message

Resource [{}] cannot be located

What it means

SamlUtils.buildSignatureValidationFilter() loads SAML metadata signing/validation material from the given Resource. If the resource does not exist or is unreadable, it logs this warning and returns null, meaning no signature validation filter will be built. Callers must handle the null filter or metadata signatures will not be validated as intended.

Solutions

  1. Verify the configured resource path exists and is readable by the CAS process (check container volume mounts)
  2. Fix the cas.authn.saml.* signature-metadata property to point at the correct file/classpath location
  3. Handle the null return: decide whether failing fast (throw) is safer than silently skipping signature validation
  4. Re-deploy including the resource if it was supposed to be on the classpath

Example fix

// before: silently null filter
val filter = SamlUtils.buildSignatureValidationFilter(resource);
// after: guard first
if (!ResourceUtils.doesResourceExist(resource)) {
    throw new FileNotFoundException(resource.getFilename());
}
val filter = SamlUtils.buildSignatureValidationFilter(resource);
Defensive patterns

Strategy: validation

Validate before calling

// precheck the resource before building the filter
if (!ResourceUtils.doesResourceExist(signatureResource)) {
    throw new FileNotFoundException(signatureResource.getDescription());
}

Type guard

function hasFilter(f) { return f != null; }

Try / catch

val filter = SamlUtils.buildSignatureValidationFilter(res);
if (filter == null) throw new IllegalStateException('signature metadata missing: ' + res);

Prevention

When it happens

Trigger: Passing a signature metadata Resource whose file path is wrong, the file is missing on disk, or the classpath:/http: location cannot be resolved by ResourceUtils.doesResourceExist.

Common situations: Typo in the signature metadata file path in cas.authn.saml properties; the signing certificate/metadata file was moved or deleted after deployment; running in a container where the mounted metadata volume is absent; classpath resource not packaged into the WAR.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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

Appendix: source

Thrown at support/cas-server-support-saml-core-api/src/main/java/org/apereo/cas/support/saml/SamlUtils.java:286

        try {
            val resource = resourceLoader.getResource(signatureResourceLocation);
            return buildSignatureValidationFilter(resource);
        } catch (final Exception e) {
            LOGGER.debug(e.getMessage(), e);
        }
        return null;
    }

    /**
     * Build signature validation filter if needed.
     *
     * @param signatureResourceLocation the signature resource location
     * @return the metadata filter
     * @throws Exception the exception
     */
    public static @Nullable SignatureValidationFilter buildSignatureValidationFilter(final Resource signatureResourceLocation) throws Exception {
        if (!ResourceUtils.doesResourceExist(signatureResourceLocation)) {
            LOGGER.warn("Resource [{}] cannot be located", signatureResourceLocation);
            return null;
        }

        val keyInfoProviderList = new ArrayList<KeyInfoProvider>(4);
        keyInfoProviderList.add(new RSAKeyValueProvider());
        keyInfoProviderList.add(new DSAKeyValueProvider());
        keyInfoProviderList.add(new DEREncodedKeyValueProvider());
        keyInfoProviderList.add(new InlineX509DataProvider());

        LOGGER.debug("Attempting to resolve credentials from [{}]", signatureResourceLocation);
        val credential = buildCredentialForMetadataSignatureValidation(signatureResourceLocation);
        LOGGER.info("Successfully resolved credentials from [{}]", signatureResourceLocation);
        Objects.requireNonNull(credential, "No credential found");

        LOGGER.debug("Configuring credential resolver for key signature trust engine @ [{}]",
            credential.getCredentialType().getSimpleName());
        val resolver = new StaticCredentialResolver(credential);
        val keyInfoResolver = new BasicProviderKeyInfoCredentialResolver(keyInfoProviderList);

View on GitHub (pinned to e7288fc434)