spring-projects/spring-security · error · Saml2Exception

Unable to resolve Builder for

Error message

Unable to resolve Builder for 

What it means

This is the metadata-package copy of OpenSaml5Template.build(): it looks up an XMLObjectBuilder for the given QName in OpenSAML's registry and throws Saml2Exception when none is registered, meaning OpenSAML cannot construct the requested element type because providers were not initialized or the element is unknown to the registry.

Source

Thrown at saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/metadata/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. Initialize OpenSAML default providers before building (OpenSamlInitializationService.initialize() or Spring Security's bootstrap).
  2. Use the element's DEFAULT_ELEMENT_NAME constant instead of a hand-built QName.
  3. Add the OpenSAML module providing the element (opensaml-saml-api/impl, opensaml-saml-ext, etc.).
  4. For custom elements, register a builder via XMLObjectProviderRegistry.registerObjectProvider(...).

Example fix

// before
template.build(new QName("urn:oasis:names:tc:SAML:2.0:metadata", "EntityDescriptor")); // wrong ns -> no builder
// after
template.build(EntityDescriptor.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
            + "; initialize providers and check module dependencies", ex);
}

Prevention

When it happens

Trigger: Calling OpenSaml5Template.build(QName) for a metadata (or other) element with no registered builder — OpenSAML bootstrap not run, wrong QName namespace/local part, or an extension element (e.g. entity attributes) from a module that is not on the classpath.

Common situations: Generating SAML metadata before OpenSamlInitializationService.initialize() registered default providers; building EntityDescriptor sub-elements from extension namespaces without the corresponding OpenSAML dependency; hand-built QName literals with typo'd namespace URIs.

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/8e3ac417425b3f22. Report an issue: GitHub.