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

  1. Ensure OpenSAML default providers are initialized before building (call OpenSamlInitializationService.initialize() or let Spring Security's bootstrap run).
  2. Verify the QName namespace URI and local part exactly match a registered SAML element (prefer the element's DEFAULT_ELEMENT_NAME constant).
  3. Add the OpenSAML module that provides the element (opensaml-saml-api/impl for profile elements, opensaml-messaging-api for core objects).
  4. 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

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


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/66d6ea6d7f6c5f49. Report an issue: GitHub.