apereo/cas · error · FileNotFoundException
Resource does not exist or is unreadable
Error message
Resource does not exist or is unreadable
What it means
AbstractMetadataResolverAdapter.getResourceInputStream opens the configured SAML metadata Resource for parsing. If resource.exists() or resource.isReadable() fails, it throws a FileNotFoundException with this message before loadMetadataFromResource can build a resolver. It means the metadata file/URL is missing, wrong, or not readable by the CAS process.
Solutions
- Check the configured metadata resource path/URL for typos and confirm the file exists at that exact location
- Fix filesystem permissions so the CAS process user can read the file
- If it's a classpath resource, ensure the metadata file is packaged inside the overlay at that path
- For remote URLs, verify reachability and that the HTTP fetch produces a readable stream
- Restart/redeploy after restoring the metadata file; then reload the metadata resolver
Example fix
// before cas.authn.saml-idp.metadata.location=file:/etc/cas/saml/idp-metadata.xml // file missing // after: place file and grant read access cp idp-metadata.xml /etc/cas/saml/ && chmod 644 /etc/cas/saml/idp-metadata.xml
Defensive patterns
Strategy: validation
Validate before calling
// check the metadata resource before handing it to the resolver adapter
Resource res = resourceLoader.getResource(metadataLocation);
if (!res.exists()) throw new IllegalStateException("Metadata resource missing: " + metadataLocation);
if (!res.isReadable()) throw new IllegalStateException("Metadata resource unreadable: " + metadataLocation); Prevention
- Verify metadata file paths/URLs in configuration at deploy time (fail fast health check)
- Mount metadata files into containers and set correct ownership for the CAS user
- Use classpath: resources carefully and confirm they are packaged in the WAR
- Monitor metadata resource availability with a startup probe
When it happens
Trigger: loadMetadataFromResource -> getResourceInputStream whenever the configured metadata Resource (file path, classpath entry, or URL) does not exist, was deleted/moved, or the OS/file permissions prevent reading.
Common situations: Typo'd metadata location in the SamlRegisteredService or samlIdp properties; file exists but CAS runs as a user without read permission; classpath resource not packaged; remote metadata URL unreachable in a way Spring Resource reports as nonexistent; container image without the metadata file mounted.
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
- Metadata directory location cannot be located/created
- Metadata directory location cannot be located/created
- Resource [ ] cannot be located
- Metadata artifact at
- No assertion consumer service could be found for entity
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/c81be24cbf8f1b91.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-saml-mdui-core/src/main/java/org/apereo/cas/support/saml/mdui/AbstractMetadataResolverAdapter.java:103
val resolvers = new ArrayList<MetadataResolver>(entries.size());
entries.forEach(entry -> {
val resource = entry.getKey();
LOGGER.debug("Loading [{}]", resource.getFilename());
resolvers.addAll(loadMetadataFromResource(entry.getValue(), resource, entityId));
});
FunctionUtils.doUnchecked(_ -> {
this.metadataResolver.setId(ChainingMetadataResolver.class.getCanonicalName());
this.metadataResolver.setResolvers(resolvers);
LOGGER.debug("Collected metadata from [{}] resolvers(s). Initializing aggregate resolver...", resolvers.size());
this.metadataResolver.initialize();
LOGGER.info("Metadata aggregate initialized successfully.");
});
}
protected InputStream getResourceInputStream(final Resource resource, final String entityId) throws IOException {
LOGGER.debug("Locating metadata resource from input stream.");
if (!resource.exists() || !resource.isReadable()) {
throw new FileNotFoundException("Resource does not exist or is unreadable");
}
return resource.getInputStream();
}
private List<MetadataResolver> loadMetadataFromResource(final MetadataFilter metadataFilter, final Resource resource,
final String entityId) {
LOGGER.debug("Evaluating metadata resource [{}]", resource.getFilename());
try (val in = getResourceInputStream(resource, entityId)) {
if (in.available() > 0) {
LOGGER.debug("Parsing [{}]", resource.getFilename());
val document = this.configBean.getParserPool().parse(in);
return buildSingleMetadataResolver(metadataFilter, resource, document);
}
LOGGER.warn("Input stream from resource [{}] appears empty. Moving on...", resource.getFilename());
} catch (final Exception e) {
LoggingUtils.warn(LOGGER, "Could not retrieve input stream from resource. Moving on...", e);
}
return new ArrayList<>();View on GitHub (pinned to e7288fc434)