spring-projects/spring-security · error · Saml2Exception
Unable to resolve Builder for
Error message
Unable to resolve Builder for
What it means
OpenSaml5Template.build() looks up an OpenSAML XMLObjectBuilder for the given QName via the global XMLObjectProviderRegistry. When no builder is registered for that element name, the template cannot construct the XMLObject and throws this Saml2Exception. This almost always means the OpenSAML object provider initialization did not run or the element is not a known SAML element.
Source
Thrown at saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/registration/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 is initialized before building — add opensaml-saml-api/impl to the classpath and let org.springframework.security.saml2 (OpenSamlInitializationService / InitializationService) register the default providers, or call InitializationService.initialize() yourself
- Verify the QName's namespace URI and localPart exactly match the SAML element (e.g. Response.DEFAULT_ELEMENT_NAME), not a hand-typed string
- Check for conflicting opensaml jar versions on the classpath that may break provider registration
- If building a custom element, register an XMLObjectBuilder for it with the BuilderRegistry before calling build
Example fix
// before
XMLObject obj = template.build(new QName("urn:oasis:names:tc:SAML:2.0:protocol", "Resposne"));
// after
XMLObject obj = template.build(Response.DEFAULT_ELEMENT_NAME); Defensive patterns
Strategy: validation
Validate before calling
InitializationService.initialize(); // once at startup, before any build()
if (XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(elementName) == null) {
throw new IllegalStateException("No OpenSAML builder for " + elementName);
} Type guard
boolean canBuild(QName name) {
return XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(name) != null;
} Try / catch
try {
T obj = template.build(elementName);
} catch (Saml2Exception ex) {
throw new IllegalStateException("Unknown/unregistered element: " + elementName, ex);
} Prevention
- Call OpenSamlInitializationService.initialize() (or InitializationService.initialize()) at application startup
- Use the *DEFAULT_ELEMENT_NAME constants instead of hand-written QNames
- Keep a single consistent OpenSAML 5 version on the classpath
When it happens
Trigger: Calling OpenSaml5Template.build(QName) with a QName whose builder is absent from XMLObjectProviderRegistrySupport — e.g. a typo'd namespace URI or localPart, or building before OpenSAML's InitializationService has registered the standard SAML providers (typically done by OpenSamlInitializationService in this library).
Common situations: Using a custom/unknown element QName; constructing the template manually without triggering OpenSAML bootstrap initialization (no class from opensaml-saml-api touched first); mixing OpenSAML 4/5 jars so registry registration fails; building extension elements from a profile whose providers were never registered.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Unable to resolve Builder for " + elementName
- 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/3f1e628be90a13bc.
Report an issue: GitHub.