spring-projects/spring-security · error · IllegalArgumentException
metadataResolver must be an IterableMetadataSource or have a
Error message
metadataResolver must be an IterableMetadataSource or have a RoleMetadataIndex
What it means
BaseOpenSamlAssertingPartyMetadataRepository's constructor requires the supplied resolver adapter to either expose a RoleMetadataIndex (allowing role-based entity lookups) or be an IterableMetadataSource (allowing plain iteration). Neither being true makes the repository unable to enumerate IDP EntityDescriptors, so it rejects the configuration with this IllegalArgumentException.
Source
Thrown at saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/BaseOpenSamlAssertingPartyMetadataRepository.java:68
* Construct an {@link BaseOpenSamlAssertingPartyMetadataRepository} using the
* provided {@link MetadataResolver}.
*
* <p>
* The {@link MetadataResolver} should either be of type
* {@link IterableMetadataSource} or it should have a {@link RoleMetadataIndex}
* configured.
* @param metadataResolver the {@link MetadataResolver} to use
*/
BaseOpenSamlAssertingPartyMetadataRepository(MetadataResolverAdapter metadataResolver) {
Assert.notNull(metadataResolver, "metadataResolver cannot be null");
if (isRoleIndexed(metadataResolver.metadataResolver)) {
this.descriptors = this::allIndexedEntities;
}
else if (metadataResolver.metadataResolver instanceof IterableMetadataSource source) {
this.descriptors = source::iterator;
}
else {
throw new IllegalArgumentException(
"metadataResolver must be an IterableMetadataSource or have a RoleMetadataIndex");
}
this.metadataResolver = metadataResolver;
}
private static boolean isRoleIndexed(MetadataResolver resolver) {
if (!(resolver instanceof AbstractBatchMetadataResolver batch)) {
return false;
}
for (MetadataIndex index : batch.getIndexes()) {
if (index instanceof RoleMetadataIndex) {
return true;
}
}
return false;
}
private Iterator<EntityDescriptor> allIndexedEntities() {View on GitHub (pinned to 96852e8860)
Solutions
- Add a RoleMetadataIndex to your resolver: metadataResolver.setIndexes(Set.of(new RoleMetadataIndex())) before initialize()
- Or implement/wrap the resolver as an IterableMetadataSource that can iterate all entities
- Use one of Spring Security's provided adapters (e.g. ResourceBackedMetadataResolver via initialize()) instead of a custom one
- Review the repository Javadoc/constructor for the accepted resolver shapes
Example fix
// before
var adapter = new MetadataResolverAdapter(myPlainResolver) {};
// after
myPlainResolver.setIndexes(Set.of(new RoleMetadataIndex()));
myPlainResolver.initialize();
var adapter = new MetadataResolverAdapter(myPlainResolver) {}; Defensive patterns
Strategy: validation
Validate before calling
void requireUsableResolver(MetadataResolver r) {
boolean roleIndexed = r != null && r.getIndexes() != null
&& r.getIndexes().stream().anyMatch(RoleMetadataIndex.class::isInstance);
boolean iterable = r instanceof IterableMetadataSource;
if (!roleIndexed && !iterable) {
throw new IllegalArgumentException("resolver needs RoleMetadataIndex or IterableMetadataSource");
}
} Try / catch
try {
var repo = new ResourceBackedAssertingPartyMetadataRepository(resource);
} catch (Saml2Exception | IllegalArgumentException ex) {
logger.error("Bad metadata resolver configuration: {}", ex.getMessage(), ex);
throw ex;
} Prevention
- Always set Set.of(new RoleMetadataIndex()) on custom resolvers passed to these repositories
- Prefer Spring Security's own ResourceBackedMetadataResolver/initialize() helper over raw OpenSAML resolvers
- Unit-test repository construction with your resolver at startup (fail fast)
When it happens
Trigger: Constructing BaseOpenSamlAssertingPartyMetadataRepository (or a subclass like the file-system/JDBC variants) with a MetadataResolverAdapter whose metadataResolver is not role-indexed and does not implement IterableMetadataSource.
Common situations: Passing a custom OpenSAML MetadataResolver (e.g. a plain FilesystemMetadataResolver or DynamicEntityMetadataResolver) into a resource-backed repository without wrapping it or adding a RoleMetadataIndex; upgrading Spring Security where repository construction API changed; hand-rolling the adapter for tests.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Can not set rememberMeCookieName and custom rememberMeServic
- Failed to parse address 'X'
- Metadata response is missing the necessary IDPSSODescriptor
- invalid_destination
- registration not found
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/9f621134d352981c.
Report an issue: GitHub.