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(QName) asks the OpenSAML XMLObjectBuilderFactory for a builder registered for the given element QName. If OpenSAML has no builder for that element name (unknown element, wrong namespace, or uninitialized registries), it throws Saml2Exception('Unable to resolve Builder for <elementName>').
Source
Thrown at saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/authentication/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
- Use the constants from net.shibboleth.opensaml or org.opensaml.saml (e.g. LogoutRequest.DEFAULT_ELEMENT_NAME) instead of hand-built QNames so namespace and element name match exactly.
- Call OpenSamlInitializationService.initialize() at startup so default builders are registered.
- For custom extension elements, register an XMLObjectBuilder for their QName via XMLObjectProviderRegistrySupport / an ObjectProvider.
- Print the failing QName and compare its namespaceURI/localPart against OpenSAML's registered element names.
Example fix
// before
QName qname = new QName("logout", "LogoutRequest");
LogoutRequest req = template.build(qname);
// after
LogoutRequest req = template.build(LogoutRequest.DEFAULT_ELEMENT_NAME); Defensive patterns
Strategy: validation
Validate before calling
XMLObjectBuilder<?> b = XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(elementName);
if (b == null) {
throw new IllegalArgumentException("No OpenSAML builder registered for " + elementName);
} Try / catch
try {
T obj = template.build(elementName);
} catch (Saml2Exception ex) {
throw new IllegalStateException("OpenSAML builder missing — check initialization and QName", ex);
} Prevention
- Use DEFAULT_ELEMENT_NAME constants instead of hand-built QNames.
- Call OpenSamlInitializationService.initialize() in a @PostConstruct or startup bean.
- Register builders for custom extension elements up front.
- Unit-test element construction in a context that mimics production bootstrap.
When it happens
Trigger: Calling template.build(qName) with a QName not registered in OpenSAML's builder factory — custom extension elements, typo'd namespace URIs, or building SAML elements before OpenSAML bootstrap has registered defaults.
Common situations: Constructing LogoutRequest/AttributeQuery or vendor-extension elements with a hand-built QName whose namespace URI or prefix spelling is wrong; forgetting OpenSamlInitializationService.initialize() in a custom setup; mixing OpenSAML 4-era element constants with OpenSAML 5 namespaces.
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
- Unsupported element of type
- Failed to deserialize payload
- subject_not_found
- Unsupported element of type " + element.getTagName()
- Failed to deserialize payload
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/dde2698a269678d1.
Report an issue: GitHub.