spring-projects/spring-security · error · Saml2Exception
Unable to resolve Builder for " + elementName
Error message
Unable to resolve Builder for " + elementName
What it means
OpenSaml5Template.build() asks OpenSAML's global XMLObjectProviderRegistry for a builder registered under the given QName and throws this Saml2Exception when none is registered. It means OpenSAML has no provider that can construct XML objects for that element name — typically because OpenSAML initialization (which registers the default providers) did not run, or the element belongs to a module/namespace that is not registered.
Source
Thrown at saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/authentication/logout/OpenSaml5Template.java:132
import org.springframework.security.saml2.core.Saml2ParameterNames;
import org.springframework.security.saml2.core.Saml2X509Credential;
import org.springframework.util.Assert;
import org.springframework.web.util.UriComponentsBuilder;
import org.springframework.web.util.UriUtils;
/**
* For internal use only. Subject to breaking changes at any time.
*/
@NullMarked
final class OpenSaml5Template implements OpenSamlOperations {
private static final Log logger = LogFactory.getLog(OpenSaml5Template.class);
@Override
public <T extends XMLObject> T build(QName elementName) {
XMLObjectBuilder<?> builder = XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(elementName);
if (builder == null) {
throw new Saml2Exception("Unable to resolve Builder for " + elementName);
}
return (T) builder.buildObject(elementName);
}
@Override
public <T extends XMLObject> T deserialize(String serialized) {
return deserialize(new ByteArrayInputStream(serialized.getBytes(StandardCharsets.UTF_8)));
}
@Override
public <T extends XMLObject> T deserialize(InputStream serialized) {
try {
ParserPool pool = XMLObjectProviderRegistrySupport.getParserPool();
Assert.notNull(pool, "ParserPool must be configured");
Document document = pool.parse(serialized);
Element element = document.getDocumentElement();
UnmarshallerFactory factory = XMLObjectProviderRegistrySupport.getUnmarshallerFactory();
Unmarshaller unmarshaller = factory.getUnmarshaller(element);View on GitHub (pinned to 96852e8860)
Solutions
- Ensure OpenSAML default providers are initialized before building (call OpenSamlInitializationService.initialize() or let Spring Security's bootstrap run).
- Verify the QName namespace URI and local part exactly match a registered SAML element (prefer the element's DEFAULT_ELEMENT_NAME constant).
- Add the OpenSAML module that provides the element (opensaml-saml-api/impl for profile elements, opensaml-messaging-api for core objects).
- For custom elements, register a builder via XMLObjectProviderRegistry.registerObjectProvider(...).
Example fix
// before
template.build(new QName("urn:oasis:names:tc:SAML:2.0:assertion", "Response")); // providers not initialized -> Saml2Exception
// after
OpenSamlInitializationService.initialize();
XMLObject response = template.build(Response.DEFAULT_ELEMENT_NAME); Defensive patterns
Strategy: try-catch
Validate before calling
OpenSamlInitializationService.initialize();
if (XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(elementName) == null) {
throw new IllegalStateException("No OpenSAML builder registered for " + elementName);
} Type guard
static boolean hasBuilder(QName elementName) {
return XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(elementName) != null;
} Try / catch
try {
T obj = template.build(elementName);
} catch (Saml2Exception ex) {
throw new IllegalStateException("OpenSAML builder missing for " + elementName
+ "; ensure OpenSamlInitializationService.initialize() ran and required modules are on the classpath", ex);
} Prevention
- Call OpenSamlInitializationService.initialize() once at startup before any OpenSAML usage.
- Prefer DEFAULT_ELEMENT_NAME constants over hand-built QName literals.
- Declare opensaml-saml-api/impl dependencies for every SAML profile element you build.
- Check hasBuilder(elementName) in startup health checks for custom elements.
When it happens
Trigger: Calling OpenSaml5Template.build(QName) with a QName whose element type has no registered XMLObjectBuilder — building a SAML element before OpenSamlInitializationService.initialize() ran, a hand-built QName with a wrong namespace URI or local part, or a custom extension element whose provider was never registered.
Common situations: Using OpenSaml5Template in a plain Spring context where the OpenSAML bootstrap never runs; requesting elements from SAML profiles or extensions whose opensaml module dependency is absent; constructing QName literals with a typo'd namespace; upgrading Spring Security/OpenSAML and referencing moved elements.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Unable to resolve Builder for
- Unable to resolve Builder for
- Unsupported element of type
- Failed to deserialize payload
- subject_not_found
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/66d6ea6d7f6c5f49.
Report an issue: GitHub.