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 element QName via the global XMLObjectProviderRegistry. OpenSAML throws this Saml2Exception when no builder has been registered for that element name, meaning the corresponding OpenSAML module's ObjectProvider init was never run or the QName is not a recognized SAML element. Spring Security cannot construct the requested XMLObject, so it fails fast instead of returning null.
Source
Thrown at saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/web/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
- Call OpenSamlInitializationService.initialize() (or ensure the OpenSAML InitializationService runs) before using OpenSaml5Template so all default object providers are registered.
- Verify the QName's namespace URI and local part exactly match a SAML element (e.g. Assertion.DEFAULT_ELEMENT_NAME) rather than a hand-built QName.
- Check for conflicting OpenSAML versions on the classpath (only opensaml-core/opensaml-xmlsec etc. v5 should be present) and re-run the provider registration.
- If using a custom element, register its builder via the XMLObjectProviderRegistry (XMLObjectProviderRegistrySupport.getRegistry().registerObjectProvider(...)).
Example fix
// before
QName name = new QName("Assertion"); // no namespace -> unresolvable
Assertion a = template.build(name);
// after
OpenSamlInitializationService.initialize();
Assertion a = template.build(Assertion.DEFAULT_ELEMENT_NAME); // canonical QName with SAML namespace Defensive patterns
Strategy: validation
Validate before calling
OpenSamlInitializationService.initialize();
if (XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(elementName) == null) {
throw new IllegalStateException("No OpenSAML builder registered for " + elementName);
} Try / catch
try { T obj = template.build(elementName); } catch (Saml2Exception ex) { log.error("Builder missing for {}", elementName, ex); throw ex; } Prevention
- Call OpenSamlInitializationService.initialize() at application startup
- Always use *.DEFAULT_ELEMENT_NAME constants instead of hand-built QNames
- Keep a single OpenSAML 5 version on the classpath
When it happens
Trigger: Calling OpenSaml5Template.build(QName) with an element name for which XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(elementName) returns null — e.g. a QName whose namespace/qualified name does not match any registered SAML object provider.
Common situations: Using a custom or misspelled QName; calling build() before OpenSAML's InitializationService/global registry was initialized (typically done by OpenSamlInitializationService.initialize()); mixing OpenSAML 4 and 5 jars on the classpath so providers register under a different registry; using an element from a SAML profile (e.g. ECP, metadata extensions) whose module is not initialized.
Related errors
- Unable to resolve Builder for
- Spring Security does not support OpenSAML {Version.getVersio
- Spring Security does not support OpenSAML {Version.getVersio
- Saml2Exception wrapping MarshallingException while re-marsha
- Unsupported element of type
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/b9c02cbc8b4b64d7.
Report an issue: GitHub.